BAL and Maple Release 2.2
Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bal_release/src/apps/bal_cli/Makefile b/bal_release/src/apps/bal_cli/Makefile
new file mode 100644
index 0000000..52c885f
--- /dev/null
+++ b/bal_release/src/apps/bal_cli/Makefile
@@ -0,0 +1,39 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+#
+# BAL core CLI application
+#
+MOD_NAME = bal_cli
+MOD_DEPS = bal_core dev_log cli os_cli bal_api_cli topology cmdline
+MOD_DEPS_OPT = omcisvc
+MOD_TYPE = app
+
+srcs = bal_cli_app.c
diff --git a/bal_release/src/apps/bal_cli/bal_cli_app.c b/bal_release/src/apps/bal_cli/bal_cli_app.c
new file mode 100644
index 0000000..40a6229
--- /dev/null
+++ b/bal_release/src/apps/bal_cli/bal_cli_app.c
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_cli_app.c
+ * @brief BAL CLI application
+ * @addtogroup ctrlr
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bal_core.h>
+#include <bal_cli.h>
+
+#ifdef OMCI_SVC
+#include <omci_svc.h>
+#include <omci_svc_cli.h>
+#endif
+
+
+/*****************************************************************************/
+/**
+ * @brief The main entry point for the Bal Core
+ *
+ * A function to initialize and start the Bal Core. The user
+ * supplied command line arguments are processed, the internal CLI is
+ * initialized, as are all of the components in the Core. User input to
+ * the CLI is then processed. This function does not return until the
+ * user quits the CLI, at which time the BAL core terminates operation.
+ *
+ * Errors encountered during the execution of this function are considered
+ * to be fatal.
+ *
+ * @param argc command line argument count
+ *
+ * @param argv pointer to command line argument list
+ *
+ * @returns 0 on success, or -EINVAL when an error is encountered
+ *
+ *****************************************************************************/
+int main(int argc, char *argv[])
+{
+ bcmos_errno ret;
+
+ do
+ {
+ /* Init BAL components */
+ ret = bcmbal_init_all(argc, argv, NULL);
+ if (BCM_ERR_OK != ret)
+ break;
+
+ /* Execute init script if any */
+ ret = bcmbal_cli_exec_init_script();
+ if (BCM_ERR_OK != ret)
+ break;
+
+ /* Let everything run until CLI terminates */
+ while (!bcmbal_cli_is_terminated())
+ bcmos_usleep(1000000);
+ }
+ while (0);
+
+ /* Cleanup */
+ bcmbal_cli_finish();
+ bcmbal_finish();
+ bcmos_exit();
+
+ return (BCM_ERR_OK == ret) ? 0 : -1;
+}
+
+
+/*@}*/
diff --git a/bal_release/src/common/bal_app_utils/Makefile b/bal_release/src/common/bal_app_utils/Makefile
new file mode 100644
index 0000000..2551bf6
--- /dev/null
+++ b/bal_release/src/common/bal_app_utils/Makefile
@@ -0,0 +1,36 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# Common utilities
+#
+MOD_NAME = bal_app_utils
+MOD_TYPE = lib
+MOD_DEPS = dev_log maple_sdk
+srcs = bal_app_common_utils.c
diff --git a/bal_release/src/common/bal_app_utils/bal_app_common_utils.c b/bal_release/src/common/bal_app_utils/bal_app_common_utils.c
new file mode 100755
index 0000000..83894d6
--- /dev/null
+++ b/bal_release/src/common/bal_app_utils/bal_app_common_utils.c
@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_app_common_utils.c
+ * @brief BAL app common Utilities functionality
+ *
+ * @addtogroup util
+ */
+
+/*@{*/
+
+#include "bal_app_common_utils.h"
+
+/*****************************************************************************/
+/**
+* @brief app_util_parse_ip_port
+*
+* This routine is used to parse the user supplied IP address and port of the
+* remote MAC device.
+*
+* @param ip_port A string containing the IP:port to parse
+*
+* @param ip The IP address that results from the parsing function
+*
+* @param port The port that results from the parsing function
+*
+* @return bcmos_errno
+*/
+/*****************************************************************************/
+bcmos_errno app_util_parse_ip_port(const char *ip_port, uint32_t *ip, uint16_t *port)
+{
+ int n;
+ uint32_t ip1, ip2, ip3, ip4, pp;
+
+ if (!ip_port)
+ {
+ bcmos_printf("ERR: ip_port is not set\n");
+ return BCM_ERR_PARM;
+ }
+ n = sscanf(ip_port, "%u.%u.%u.%u:%u", &ip1, &ip2, &ip3, &ip4, &pp);
+ if (n != 5 || ip1 > 0xff || ip2 > 0xff || ip3 > 0xff || ip4 > 0xff || pp > 0xffff)
+ {
+ bcmos_printf("ERR: Can't parse %s. Must be ip_address:port\n", ip_port);
+ return BCM_ERR_PARM;
+ }
+ *ip = (ip1 << 24) | (ip2 << 16) | (ip3 << 8) | ip4;
+ *port = pp;
+ return BCM_ERR_OK;
+}
+
+/*@}*/
+
diff --git a/bal_release/src/common/bal_app_utils/bal_app_common_utils.h b/bal_release/src/common/bal_app_utils/bal_app_common_utils.h
new file mode 100755
index 0000000..1db1b9f
--- /dev/null
+++ b/bal_release/src/common/bal_app_utils/bal_app_common_utils.h
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_app_common_utils.h
+ * @brief BAL Utilities include file
+ *
+ * @defgroup util Bal App Util Routines
+ * @ingroup lib
+ */
+
+#ifndef _BAL_COMMON_UTILS_H
+#define _BAL_COMMON_UTILS_H
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include <bal_utils_msg.h>
+#include <bal_msg_type.h>
+#include <bal_objs.h>
+
+bcmos_errno app_util_parse_ip_port(const char *ip_port, uint32_t *ip, uint16_t *port);
+
+/*@}*/
+
+#endif /* _BAL_COMMON_UTILS_H*/
diff --git a/bal_release/src/common/cli b/bal_release/src/common/cli
new file mode 120000
index 0000000..8573c77
--- /dev/null
+++ b/bal_release/src/common/cli
@@ -0,0 +1 @@
+../../3rdparty/maple/sdk/host_reference/cli
\ No newline at end of file
diff --git a/bal_release/src/common/config/bcm_config.h b/bal_release/src/common/config/bcm_config.h
new file mode 100644
index 0000000..9221c1a
--- /dev/null
+++ b/bal_release/src/common/config/bcm_config.h
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * <: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 BCMOLT_CONFIG_H_
+#define BCMOLT_CONFIG_H_
+
+/** \defgroup config Configuration Constants
+ * Configuration constants that must be revised by customer
+ * @{
+ */
+
+#define BCMTR_MAX_OLTS 1 /**< Max number of OLTs */
+
+/** @} */
+
+
+#endif /* BCMOLT_CONFIG_H_ */
diff --git a/bal_release/src/common/db_engine/Makefile b/bal_release/src/common/db_engine/Makefile
new file mode 100644
index 0000000..23b64f6
--- /dev/null
+++ b/bal_release/src/common/db_engine/Makefile
@@ -0,0 +1,36 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# Data Base engine
+#
+MOD_NAME = db
+MOD_TYPE = lib
+
+srcs = bcm_db_engine.c
diff --git a/bal_release/src/common/db_engine/bcm_db_engine.c b/bal_release/src/common/db_engine/bcm_db_engine.c
new file mode 100644
index 0000000..dc4f19a
--- /dev/null
+++ b/bal_release/src/common/db_engine/bcm_db_engine.c
@@ -0,0 +1,1606 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/*
+ * Data Base Engine
+ *
+ * Proprietary and confidential.
+ */
+#include <bcmos_system.h>
+#include <bcm_db_engine.h>
+
+/* DB trace level */
+bcmos_trace_level bcmdb_trace_level = BCMOS_TRACE_LEVEL_ERROR;
+
+#define BCMDB_TRACE(level, fmt, args...) \
+ do { \
+ if (level <= bcmdb_trace_level) \
+ bcmos_trace(level, "%s#%d> " fmt, __FUNCTION__, __LINE__, ## args); \
+ } while (0)
+
+/* Print error trace conditionally, depending on the current trace level */
+#define BCMDB_TRACE_ERROR(fmt, args...) \
+ BCMDB_TRACE(BCMOS_TRACE_LEVEL_ERROR, "DB ERR: %s#%d> " fmt, __FUNCTION__, __LINE__, ## args)
+
+/* Print warning trace conditionally, depending on the current trace level */
+#define BCMDB_TRACE_WARNING(fmt, args...) \
+ BCMDB_TRACE(BCMOS_TRACE_LEVEL_WARNING, "DB WARN: %s#%d> " fmt, __FUNCTION__, __LINE__, ## args)
+
+/* Print info trace conditionally, depending on the current trace level */
+#define BCMDB_TRACE_INFO(fmt, args...) \
+ BCMDB_TRACE(BCMOS_TRACE_LEVEL_INFO, "DB INFO: %s#%d> " fmt, __FUNCTION__, __LINE__, ## args)
+
+/* Enable debug prints */
+#define BCMDB_DEBUG
+
+#ifdef BCMDB_DEBUG
+
+/* Print debug trace conditionally, depending on the current trace level */
+#define BCMDB_TRACE_DEBUG(fmt, args...) \
+ BCMDB_TRACE(BCMOS_TRACE_LEVEL_DEBUG, "DB DBG: %s#%d> " fmt, __FUNCTION__, __LINE__, ## args)
+
+#else
+
+#define BCMDB_TRACE_DEBUG(fmt, args...)
+
+#endif
+
+
+
+/** Data base entry
+ * \ingroup bcmdb
+ */
+struct bcmdb_entry
+{
+ void *data; /* Set or record */
+ uint8_t flags;
+#define BCMDB_FLAG_VALID 0x01 /**< Entry is valid */
+#define BCMDB_FLAG_RECORD 0x02 /**< Record */
+#define BCMDB_FLAG_SOS 0x10 /**< Set of sets */
+ uint8_t read_count;
+ uint8_t write_pending;
+ uint8_t ffu;
+};
+
+/** Set/Record change notification
+ * \ingroup bcmdb
+ */
+typedef struct bcmdb_notify
+{
+ struct bcmdb_notify *next;
+ bcmdb_notify_cb cb;
+ long cb_priv;
+} bcmdb_notify;
+
+/** Data Base Set control block
+ * \ingroup bcmdb
+ */
+struct bcmdb_set
+{
+ bcmdb_entry entry; /**< Common fields for set and record */
+ char *name; /**< Set name */
+ bcmdb_set *parent; /**< Set parent */
+ bcmdb_key my_key; /**< Key in the parent set */
+ int max_entries; /**< Max number of elements in the set. -1=inlimited */
+ int num_entries; /**< Current number of elements in the set */
+ int entry_size; /**< Set entry size. */
+ int magic; /**< Magic number */
+#define BCMDB_MAGIC_ACTIVE_SET (('a'<<24) | ('s'<<16) | ('e'<<8) | 't')
+#define BCMDB_MAGIC_FREE_SET (('f'<<24) | ('s'<<16) | ('e'<<8) | 't')
+
+ /** Get next element */
+ bcmdb_key (*entry_get_next)(const bcmdb_set *this, bcmdb_key cur);
+
+ /** Add new entry. returns 0 if ok */
+ int (*entry_new)(bcmdb_set *this, bcmdb_key key, const void *data);
+
+ /** Delete entry */
+ int (*entry_delete)(bcmdb_set *this, bcmdb_entry *entry);
+
+ /*
+ * Handle – key mapping
+ */
+
+ /** Convert entry handle to entry key */
+ bcmdb_key (*handle_to_key)(const bcmdb_set *this, const bcmdb_entry *entry);
+
+ /** Convert entry key to entry handle */
+ bcmdb_entry *(*key_to_handle)(const bcmdb_set *this, bcmdb_key key);
+
+ /*
+ * Set/Record locking
+ * entry is handle of the set or record to be locked/unlocked
+ */
+
+ /** Lock the whole set for reading */
+ void (*lock_set_read)(bcmdb_set *set);
+
+ /** Unlock set locked for reading */
+ void (*unlock_set_read)(bcmdb_set *set);
+
+ /** Lock the whole set for update */
+ long (*lock_set_modify)(bcmdb_set *set);
+
+ /** Unlock set locked for update */
+ void (*unlock_set_modify)(bcmdb_set *set, long fastlock_flags);
+
+ /** Lock the set recursively for update (SoS only) */
+ void (*lock_set_recursively_modify)(bcmdb_set *set);
+
+ /** Unlock recursively set locked for update (SoS only) */
+ void (*unlock_set_recursively_modify)(bcmdb_set *set);
+
+ /** Lock record for reading */
+ void *(*lock_record_read)(bcmdb_set *set, bcmdb_key key);
+
+ /** Release read lock */
+ void (*unlock_record_read)(bcmdb_set *set, bcmdb_key key);
+
+ /** Lock record for modification. */
+ void *(*lock_record_write)(bcmdb_set *set, bcmdb_key key, int is_deletion);
+
+ /** Release modify lock */
+ void (*unlock_record_write)(bcmdb_set *set, int is_deletion, int is_cancellation);
+
+ /** Format function that converts record data to human-readable form */
+ bcmdb_format_cb format;
+
+ /** Update notification mechanism.\n
+ * Note that notification functions are called before the actual update of the data base, so that
+ * there is an option to abort the update if needed.
+ */
+ bcmdb_notify *notify_list_head;
+
+ /** Shadow data record */
+ void *shadow_data;
+
+ /** holds the pointer to a write-locked entry */
+ bcmdb_entry *write_locked_entry ;
+
+ /** mutex that prevents multiple simultaneous updates */
+ bcmos_mutex mutex_update;
+
+ /** semaphore that holds update while there are unfinished reads */
+ bcmos_sem sem_wait_read_to_finish;
+
+ /** fastlock */
+ bcmos_fastlock fastlock;
+};
+
+
+/**< Data base record
+ * \ingroup bcmdb
+ */
+struct bcmdb_record
+{
+ struct bcmdb_entry e; /**< Entry - common part for set and record */
+};
+
+/*
+ * DB backend callbacks
+ */
+
+/*
+ * Array-based backend
+ */
+
+/** Get next element */
+static bcmdb_key _bcmdb_array_entry_get_next(const bcmdb_set *this, bcmdb_key key)
+{
+ BUG_ON(!this->entry.data);
+
+ if (key < 0)
+ key = 0;
+ else
+ ++key;
+
+ while((unsigned)key<this->max_entries)
+ {
+ bcmdb_entry *entry = (bcmdb_entry *)this->entry.data + key;
+ if ((entry->flags & BCMDB_FLAG_VALID))
+ break;
+ ++key;
+ }
+
+ if ((unsigned)key >= this->max_entries)
+ return BCMDB_KEY_NO_MORE; /* no more */
+
+ return key;
+}
+
+/*
+ * Handle – key mapping
+ */
+
+/** Convert entry handle to entry key */
+static inline bcmdb_key _bcmdb_array_handle_to_key(const bcmdb_set *this, const bcmdb_entry *entry)
+{
+ bcmdb_key key;
+
+ BUG_ON(!this);
+ BUG_ON(!entry);
+ BUG_ON(!this->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!this->entry.data);
+
+ key = entry - (bcmdb_entry *)this->entry.data;
+ if ((unsigned)key >= this->max_entries)
+ return BCMDB_KEY_INVAL;
+
+ return key;
+}
+
+
+/** Convert entry key to entry handle */
+static inline bcmdb_entry *_bcmdb_array_key_to_handle(const bcmdb_set *this, bcmdb_key key)
+{
+ BUG_ON(!this);
+ BUG_ON(!this->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!this->entry.data);
+
+ if ((unsigned long)key >= this->max_entries)
+ return NULL;
+
+ return (bcmdb_entry *)this->entry.data + key;
+}
+
+
+/** sem-based set read-lock */
+static void bcmdb_set_lock_read_sem(bcmdb_set *set)
+{
+ bcmos_mutex_lock(&set->mutex_update, BCMOS_WAIT_FOREVER);
+}
+
+
+/** sem-based set read-unlock */
+static void bcmdb_set_unlock_read_sem(bcmdb_set *set)
+{
+ bcmos_mutex_unlock(&set->mutex_update);
+}
+
+
+/** sem-based set modify-lock */
+static long bcmdb_set_lock_modify_sem(bcmdb_set *set)
+{
+ bcmos_mutex_lock(&set->mutex_update, BCMOS_WAIT_FOREVER);
+ return 0;
+}
+
+
+/** sem-based set modify-unlock */
+static void bcmdb_set_unlock_modify_sem(bcmdb_set *set, long fastlock_flags)
+{
+ bcmos_mutex_unlock(&set->mutex_update);
+}
+
+
+/** helper function which recursively locks all subsets of SoS
+ * for modify */
+static void bcmdb_recursive_subsets_lock_modify(bcmdb_set *sos)
+{
+ int key;
+ int left_entries = sos->num_entries;
+ bcmdb_entry *entry;
+ bcmdb_set *subset;
+
+ BUG_ON(!(sos->entry.flags & BCMDB_FLAG_SOS));
+
+ for (key = 0; key < sos->max_entries; ++key)
+ {
+ entry = sos->key_to_handle(sos, key);
+
+ if ((entry->flags & BCMDB_FLAG_VALID))
+ {
+ subset = (bcmdb_set *)entry->data;
+ subset->lock_set_recursively_modify(subset);
+
+ --left_entries;
+ /* if we handled all subsets we can break the "for" */
+ if (left_entries==0)
+ {
+ break;
+ }
+ }
+ }
+}
+
+
+/** helper function which recursively unlocks all subsets of SoS
+ * for modify */
+static void bcmdb_recursive_subsets_unlock_modify(bcmdb_set *sos)
+{
+ int key;
+ int left_entries = sos->num_entries;
+ bcmdb_entry *entry;
+ bcmdb_set *subset;
+
+ BUG_ON(!(sos->entry.flags & BCMDB_FLAG_SOS));
+
+ for (key = 0; key < sos->max_entries; ++key)
+ {
+ entry = sos->key_to_handle(sos, key);
+
+ if ((entry->flags & BCMDB_FLAG_VALID))
+ {
+ subset = (bcmdb_set *)entry->data;
+ subset->unlock_set_recursively_modify(subset);
+
+ --left_entries;
+ /* if we handled all subsets we can break the "for" */
+ if (left_entries==0)
+ {
+ break;
+ }
+ }
+ }
+}
+
+
+/** sem-based set modify-lock recursively */
+static void bcmdb_set_lock_recursively_modify_sem(bcmdb_set *set)
+{
+ BCMDB_TRACE_DEBUG("lock set modify recursively: %s\n", set->name);
+ bcmos_mutex_lock(&set->mutex_update, BCMOS_WAIT_FOREVER);
+ BCMDB_TRACE_DEBUG("mutex was locked\n");
+
+ if ((set->entry.flags & BCMDB_FLAG_SOS))
+ {
+ BCMDB_TRACE_DEBUG("going to lock the subsets\n");
+ bcmdb_recursive_subsets_lock_modify(set);
+ }
+}
+
+
+/** sem-based set modify-unlock recursively */
+static void bcmdb_set_unlock_recursively_modify_sem(bcmdb_set *set)
+{
+ BCMDB_TRACE_DEBUG("unlock set modify recursively: %s\n", set->name);
+
+ if ((set->entry.flags & BCMDB_FLAG_SOS))
+ {
+ BCMDB_TRACE_DEBUG("going to unlock the subsets\n");
+ bcmdb_recursive_subsets_unlock_modify(set);
+ }
+
+ bcmos_mutex_unlock(&set->mutex_update);
+ BCMDB_TRACE_DEBUG("mutex was unlocked\n");
+}
+
+
+/** NB-read-sem-write policy: set read lock */
+static void bcmdb_set_lock_read__nb_read_sem_write(bcmdb_set *set)
+{
+ long flags;
+
+ BCMDB_TRACE_DEBUG("lock set read: %s\n", set->name);
+ flags = bcmos_fastlock_lock(&set->fastlock);
+ ++set->entry.read_count;
+ BCMDB_TRACE_DEBUG("read_count is now: %u\n", set->entry.read_count);
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+}
+
+
+/** NB-read-sem-write policy: set read unlock */
+static void bcmdb_set_unlock_read__nb_read_sem_write(bcmdb_set *set)
+{
+ long flags;
+
+ BCMDB_TRACE_DEBUG("unlock set read: %s\n", set->name);
+
+ flags = bcmos_fastlock_lock(&set->fastlock);
+ BUG_ON(!set->entry.read_count);
+ if (!(--set->entry.read_count) &&
+ set->entry.write_pending)
+ {
+ BCMDB_TRACE_DEBUG("going to wake pending writer\n");
+
+ set->entry.write_pending = 0;
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ bcmos_sem_post(&set->sem_wait_read_to_finish);
+ }
+ else
+ {
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ }
+}
+
+
+/** NB-read-sem-write policy: set modify lock */
+static long bcmdb_set_lock_modify__nb_read_sem_write(bcmdb_set *set)
+{
+ long flags;
+
+ BCMDB_TRACE_DEBUG("lock set modify: %s\n", set->name);
+ bcmos_mutex_lock(&set->mutex_update, BCMOS_WAIT_FOREVER);
+ BCMDB_TRACE_DEBUG("mutex was locked\n");
+
+ while(1)
+ {
+ flags = bcmos_fastlock_lock(&set->fastlock);
+ if (!set->entry.read_count)
+ break;
+ /* Wait until read is completed */
+ set->entry.write_pending = 1;
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ bcmos_sem_wait(&set->sem_wait_read_to_finish, BCMOS_WAIT_FOREVER);
+ }
+ /* At this point fastlock is taken and there are no pending reads */
+
+ BCMDB_TRACE_DEBUG("fastlock is taken, no active reads\n");
+
+ return flags;
+}
+
+
+/** NB-read-sem-write policy: set modify unlock */
+static void bcmdb_set_unlock_modify__nb_read_sem_write(bcmdb_set *set, long fastlock_flags)
+{
+ BCMDB_TRACE_DEBUG("unlock set modify: %s\n", set->name);
+ bcmos_fastlock_unlock(&set->fastlock, fastlock_flags);
+ bcmos_mutex_unlock(&set->mutex_update);
+ BCMDB_TRACE_DEBUG("mutex was unlocked\n");
+}
+
+
+/** sem-read/sem-write policy: lock entry */
+static void *bcmdb_sem_read_sem_write_lock(bcmdb_set *set, bcmdb_key key, int is_deletion)
+{
+ bcmdb_entry *entry;
+ bcmos_mutex_lock(&set->mutex_update, BCMOS_WAIT_FOREVER);
+
+ if (is_deletion)
+ {
+ /* there is nothing to return in deletion case */
+ return NULL;
+ }
+
+ entry = set->key_to_handle(set, key);
+ if (!entry || !(entry->flags & BCMDB_FLAG_VALID))
+ {
+ bcmos_mutex_unlock(&set->mutex_update);
+ return NULL;
+ }
+ return entry->data;
+}
+
+/** sem-read/sem-write policy: unlock entry */
+static void bcmdb_sem_read_sem_write_unlock(bcmdb_set *set)
+{
+ bcmos_mutex_unlock(&set->mutex_update);
+}
+
+/** sem-read/sem-write policy: lock entry for reading */
+static void *bcmdb_sem_read_sem_write_lock_read(bcmdb_set *set, bcmdb_key key)
+{
+ return bcmdb_sem_read_sem_write_lock(set, key, 0) ;
+}
+
+/** sem-read/sem-write policy: unlock entry for reading */
+static void bcmdb_sem_read_sem_write_unlock_read(bcmdb_set *set, bcmdb_key key)
+{
+ bcmdb_sem_read_sem_write_unlock(set);
+}
+
+/** sem-read/sem-write policy: lock entry for writing */
+static void *bcmdb_sem_read_sem_write_lock_write(bcmdb_set *set, bcmdb_key key, int is_deletion)
+{
+ return bcmdb_sem_read_sem_write_lock(set, key, is_deletion) ;
+}
+
+/** sem-read/sem-write policy: unlock entry for writing */
+static void bcmdb_sem_read_sem_write_unlock_write(bcmdb_set *set, int is_deletion, int is_cancellation)
+{
+ bcmdb_sem_read_sem_write_unlock(set);
+}
+
+/** non-blocking-read/shadow write policy: Lock entry for reading */
+static void *bcmdb_nb_read_shadow_write_lock_read(bcmdb_set *set, bcmdb_key key)
+{
+ bcmdb_entry *entry;
+ long flags;
+
+ flags = bcmos_fastlock_lock(&set->fastlock);
+ entry = set->key_to_handle(set, key);
+ if (!entry || !(entry->flags & BCMDB_FLAG_VALID))
+ {
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ return NULL;
+ }
+ ++entry->read_count;
+
+ BCMDB_TRACE_DEBUG("lock record read: %s, key=%d new_read_count=%d\n", set->name, key, entry->read_count);
+
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ return entry->data;
+}
+
+
+/** non-blocking-read/shadow write policy: Unlock entry for reading */
+static void bcmdb_nb_read_shadow_write_unlock_read(bcmdb_set *set, bcmdb_key key)
+{
+ bcmdb_entry *entry=set->key_to_handle(set, key);
+ long flags;
+ BUG_ON(!entry);
+
+ BCMDB_TRACE_DEBUG("unlock record read: %s, key=%d\n", set->name, key);
+
+ flags = bcmos_fastlock_lock(&set->fastlock);
+ /* If write is pending - finish it and release write lock */
+ BUG_ON(!entry->read_count);
+ if (!(--entry->read_count) && set->entry.write_pending)
+ {
+ BCMDB_TRACE_DEBUG("going to wake pending writer\n");
+
+ /* Write was pending. Release write task */
+ set->entry.write_pending = 0;
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ bcmos_sem_post(&set->sem_wait_read_to_finish);
+ }
+ else
+ {
+ BCMDB_TRACE_DEBUG("read_count is now: %u\n", entry->read_count);
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ }
+}
+
+/** non-blocking-read/shadow write policy: Lock entry for
+ * writing/deletion.
+ * returned value of NULL means error only in case that
+ * is_deletion is 0 */
+static void *bcmdb_nb_read_shadow_write_lock_write(bcmdb_set *set, bcmdb_key key, int is_deletion)
+{
+ bcmdb_entry *entry;
+
+ BCMDB_TRACE_DEBUG("lock record write: %s, key=%d\n", set->name, key);
+
+ bcmos_mutex_lock(&set->mutex_update, BCMOS_WAIT_FOREVER);
+ BCMDB_TRACE_DEBUG("mutex was locked\n");
+
+ if (is_deletion)
+ {
+ /* there is nothing to return in deletion case */
+ return NULL;
+ }
+
+ /* this check is needed since mutex_update is task-aware.
+ it is not allowed for a task to lock for writing a 2nd record before unlocking the first one. */
+ if (set->write_locked_entry)
+ {
+ BCMDB_TRACE_ERROR("there is already an entry locked for writing\n");
+ bcmos_mutex_unlock(&set->mutex_update);
+ return NULL;
+ }
+
+ entry = set->key_to_handle(set, key);
+ if (!entry || !(entry->flags & BCMDB_FLAG_VALID))
+ {
+ bcmos_mutex_unlock(&set->mutex_update);
+ return NULL;
+ }
+ /* Copy data to shadow entry */
+ memcpy(set->shadow_data, entry->data, set->entry_size);
+ set->write_locked_entry = entry;
+ return set->shadow_data;
+}
+
+/** non-blocking-read/shadow write policy: Unlock entry for
+ * writing/deletion */
+static void bcmdb_nb_read_shadow_write_unlock_write(bcmdb_set *set, int is_deletion, int is_cancellation)
+{
+ bcmdb_entry *entry = set->write_locked_entry;
+ long flags;
+ void *old_data;
+
+ /* no entry is locked */
+ BUG_ON(!entry);
+
+ BCMDB_TRACE_DEBUG("unlock record write: %s\n", set->name);
+
+ /* cancellation: no need to update the entry from the shadow (or to delete the entry in case of deletion). */
+ if (is_cancellation)
+ {
+ set->write_locked_entry = NULL;
+ bcmos_mutex_unlock(&set->mutex_update);
+ return;
+ }
+
+ while(1)
+ {
+ flags = bcmos_fastlock_lock(&set->fastlock);
+ /* Wait until neither record nor set are locked for reading */
+ if (!entry->read_count && !set->entry.read_count)
+ break;
+
+ /* Read lock is active. wait */
+
+ BCMDB_TRACE_DEBUG("read lock is active. going to sleep.\n");
+
+ set->entry.write_pending = 1;
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ bcmos_sem_wait(&set->sem_wait_read_to_finish, BCMOS_WAIT_FOREVER);
+ }
+
+ /* At this point there is no read lock and fastlock is taken. */
+
+ BCMDB_TRACE_DEBUG("fastlock is taken, no active reads\n");
+
+ if (is_deletion)
+ {
+ /* delete the entry */
+ set->entry_delete(set, entry);
+ }
+ else
+ {
+ /* Exchange record data with shadow and release all locks. */
+ old_data = entry->data;
+ entry->data = set->shadow_data;
+ set->shadow_data = old_data;
+ set->write_locked_entry = NULL;
+ }
+
+ bcmos_fastlock_unlock(&set->fastlock, flags);
+ bcmos_mutex_unlock(&set->mutex_update);
+ BCMDB_TRACE_DEBUG("mutex was unlocked\n");
+}
+
+/** none policy: set read-lock */
+static inline void bcmdb_set_lock_read_dummy(bcmdb_set *set)
+{
+}
+
+/** none policy: set read-unlock */
+static inline void bcmdb_set_unlock_read_dummy(bcmdb_set *set)
+{
+}
+
+/** none policy: set modify-lock */
+static inline long bcmdb_set_lock_modify_dummy(bcmdb_set *set)
+{
+ return 0;
+}
+
+/** none policy: set modify-unlock */
+static inline void bcmdb_set_unlock_modify_dummy(bcmdb_set *set, long fastlock_flags)
+{
+}
+
+/** none policy: set modify-lock recursively */
+static void bcmdb_set_lock_recursively_modify_dummy(bcmdb_set *set)
+{
+}
+
+/** none policy: set modify-unlock recursively */
+static void bcmdb_set_unlock_recursively_modify_dummy(bcmdb_set *set)
+{
+}
+
+/** none policy: record lock */
+static inline void *bcmdb_dummy_lock(bcmdb_set *set, bcmdb_key key, int is_deletion)
+{
+ bcmdb_entry *entry;
+
+ /* there is nothing to return in deletion case */
+ if (is_deletion)
+ return NULL;
+
+ entry = set->key_to_handle(set, key);
+ if (!entry || !(entry->flags & BCMDB_FLAG_VALID))
+ return NULL;
+ return entry->data;
+}
+
+/** none policy: record unlock */
+static inline void bcmdb_dummy_unlock(bcmdb_set *set)
+{
+}
+
+/** none policy: record lock for reading */
+static inline void *bcmdb_dummy_lock_read(bcmdb_set *set, bcmdb_key key)
+{
+ return bcmdb_dummy_lock(set, key, 0);
+}
+
+/** none policy: record unlock for reading */
+static inline void bcmdb_dummy_unlock_read(bcmdb_set *set, bcmdb_key key)
+{
+ bcmdb_dummy_unlock(set);
+}
+
+/** none policy: record lock for writing */
+static inline void *bcmdb_dummy_lock_write(bcmdb_set *set, bcmdb_key key, int is_deletion)
+{
+ return bcmdb_dummy_lock(set, key, is_deletion);
+}
+
+/** none policy: record unlock for writing */
+static inline void bcmdb_dummy_unlock_write(bcmdb_set *set, int is_deletion, int is_cancellation)
+{
+ bcmdb_dummy_unlock(set);
+}
+
+
+
+/** Add new sub-set. returns 0 if ok
+ * data contains new set handle
+ */
+static int bcmdb_set_new(bcmdb_set *this, bcmdb_key key, const void *data)
+{
+ /* Although this callback takes "const void *" parameter,
+ * it is just for compatibility fith SoR->new_entry interface.
+ * For SoS this parameter is not constant on application level
+ * (see bcmdb_set_add())
+ */
+ bcmdb_entry *entry = this->key_to_handle(this, key);
+ bcmdb_set *new_set = (bcmdb_set *)(long)data;
+
+ if (!entry)
+ return BCM_ERR_PARM;
+ if ((entry->flags & BCMDB_FLAG_VALID))
+ return BCM_ERR_ALREADY;
+ ++this->num_entries;
+ entry->data = (void *)(long)data;
+ entry->flags |= BCMDB_FLAG_VALID;
+ new_set->my_key = key;
+ new_set->parent = this;
+ return 0;
+}
+
+/** Add new record. returns 0 if ok
+ * data contains record data pointer
+ */
+static int bcmdb_record_new(bcmdb_set *this, bcmdb_key key, const void *data)
+{
+ bcmdb_record *record = (bcmdb_record *)this->key_to_handle(this, key);
+ if (!record || !record->e.data)
+ return BCM_ERR_PARM;
+ if ((record->e.flags & BCMDB_FLAG_VALID))
+ return BCM_ERR_ALREADY;
+ ++this->num_entries;
+ memcpy(record->e.data, data, this->entry_size);
+ record->e.flags |= BCMDB_FLAG_VALID;
+ return 0;
+}
+
+/** Delete entry */
+static int bcmdb_entry_delete(bcmdb_set *this, bcmdb_entry *entry)
+{
+ if (!entry)
+ return BCM_ERR_PARM;
+ if (!(entry->flags & BCMDB_FLAG_VALID))
+ return BCM_ERR_ALREADY;
+ entry->flags &= ~BCMDB_FLAG_VALID;
+ --this->num_entries;
+ return 0;
+}
+
+
+/*
+ * External APIs
+ */
+
+
+/** Initialize data base engine
+ *
+ * \return
+ * 0 - OK\n
+ * <0 - error code
+ * \ingroup bcmdb
+ */
+int bcmdb_module_init(void)
+{
+ return 0;
+}
+
+
+/** Make set-of-sets control block.
+ *
+ * Helper function that creates a set of sets with reasonable defaults for all callbacks and fields.
+ * Once created, the set control block can be tuned before adding the new set to its parent set.
+ * \param[in] init set parameters
+ * \param[out] new_set set control block
+ * \return
+ * 0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_make_set_of_sets(const bcmdb_sos_init *init, bcmdb_set **new_set)
+{
+ bcmdb_set *sos;
+ bcmdb_entry *entries;
+ int rc;
+
+ /* Parameter check */
+ if (!init || !init->name || !new_set)
+ return BCM_ERR_PARM;
+ if ((init->backend_type == BCMDB_BACKEND_ARRAY) && !init->max_entries)
+ return BCM_ERR_PARM;
+
+ /* Allocate set control block and set records */
+ sos = bcmos_calloc(sizeof(bcmdb_set) + strlen(init->name) + 1);
+ if (!sos)
+ return BCM_ERR_NOMEM;
+ sos->name = (char *)(sos + 1);
+ strcpy(sos->name, init->name);
+ sos->entry_size = sizeof(bcmdb_set);
+ sos->max_entries = init->max_entries;
+ sos->my_key = BCMDB_KEY_INVAL;
+ sos->entry.flags = BCMDB_FLAG_SOS;
+ sos->magic = BCMDB_MAGIC_ACTIVE_SET;
+
+ /* Set backend callbacks */
+ switch(init->backend_type)
+ {
+ case BCMDB_BACKEND_ARRAY:
+ entries = bcmos_calloc(sizeof(bcmdb_set)*init->max_entries);
+ if (!entries)
+ {
+ bcmos_free(sos);
+ return BCM_ERR_NOMEM;
+ }
+ sos->entry.data = entries;
+ sos->entry_get_next = _bcmdb_array_entry_get_next;
+ sos->handle_to_key = _bcmdb_array_handle_to_key;
+ sos->key_to_handle = _bcmdb_array_key_to_handle;
+ sos->entry_new = bcmdb_set_new;
+ sos->entry_delete = bcmdb_entry_delete;
+ break;
+
+ default:
+ printf("Only array-based DB backend is supported\n");
+ bcmos_free(sos);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ /* Set locking callbacks. SoS locking policy is always SEMAPHORE */
+
+ /* in SoS, locking for read is same as for write (and is done recursively). */
+ sos->lock_set_read = bcmdb_set_lock_recursively_modify_sem;
+ sos->unlock_set_read = bcmdb_set_unlock_recursively_modify_sem;
+ sos->lock_set_modify = bcmdb_set_lock_modify_sem;
+ sos->unlock_set_modify = bcmdb_set_unlock_modify_sem;
+ sos->lock_set_recursively_modify = bcmdb_set_lock_recursively_modify_sem ;
+ sos->unlock_set_recursively_modify = bcmdb_set_unlock_recursively_modify_sem ;
+
+ /* create mutex_update */
+ rc = bcmos_mutex_create(&sos->mutex_update, init->os_flags);
+ if (rc)
+ {
+ bcmos_free(entries);
+ bcmos_free(sos);
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmos_fastlock_init(&sos->fastlock, init->os_flags);
+
+ *new_set = sos;
+
+ return 0;
+}
+
+
+
+
+/** Make set-of-records control block.
+ *
+ * Helper function that creates a set of records with reasonable defaults for all callbacks and fields.
+ * Once created, the set control block can be tuned before adding the new set to its parent set.
+ * \param[in] init set parameters
+ * \param[in] alloc_records true (1) - allocate memory for all records.
+ * \param[out] new_set set control block
+ * \return
+ * 0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_make_set_of_records(const bcmdb_sor_init *init, int alloc_records, bcmdb_set **new_set)
+{
+ bcmdb_set *sor;
+ bcmdb_entry *entries = NULL;
+ void *data = NULL;
+ int i;
+ int rc ;
+
+ /* Parameter check */
+ if (!init || !init->name)
+ return BCM_ERR_PARM;
+ if ((init->backend_type == BCMDB_BACKEND_ARRAY) && !init->max_entries)
+ return BCM_ERR_PARM;
+ if (!init->record_size)
+ return BCM_ERR_PARM;
+
+ /* Allocate set control block and set records */
+ sor = bcmos_calloc(sizeof(bcmdb_set) + strlen(init->name) + 1);
+ if (!sor)
+ return BCM_ERR_NOMEM;
+ sor->name = (char *)(sor + 1);
+ strcpy(sor->name, init->name);
+ sor->entry_size = init->record_size;
+ sor->max_entries = init->max_entries;
+ sor->my_key = BCMDB_KEY_INVAL;
+ sor->magic = BCMDB_MAGIC_ACTIVE_SET;
+ sor->format = init->format;
+
+ /* Set backend callbacks */
+ switch(init->backend_type)
+ {
+ case BCMDB_BACKEND_ARRAY:
+ entries = bcmos_calloc(sizeof(bcmdb_entry)*init->max_entries);
+ if (!entries)
+ {
+ bcmos_free(sor);
+ return BCM_ERR_NOMEM;
+ }
+ sor->entry.data = entries;
+ sor->entry_get_next = _bcmdb_array_entry_get_next;
+ sor->handle_to_key = _bcmdb_array_handle_to_key;
+ sor->key_to_handle = _bcmdb_array_key_to_handle;
+ sor->entry_new = bcmdb_record_new;
+ sor->entry_delete = bcmdb_entry_delete;
+
+ /* Preallocate data */
+ if (alloc_records)
+ {
+ int size = init->max_entries * init->record_size;
+ if (init->lock_policy == BCMDB_LOCK_NB_READ_SHADOW_WRITE)
+ size += init->record_size; /* room for shadow entry */
+ /* Allocate data + 1 extra for shadow area */
+ data = bcmos_calloc(size);
+ if (!data)
+ {
+ bcmos_free(entries);
+ bcmos_free(sor);
+ return BCM_ERR_NOMEM;
+ }
+ for(i=0; i<init->max_entries; i++)
+ {
+ bcmdb_entry *entry = (bcmdb_entry *)sor->entry.data + i;
+ entry->data = (void *)((long)data + i * init->record_size);
+ }
+ if (init->lock_policy == BCMDB_LOCK_NB_READ_SHADOW_WRITE)
+ {
+ sor->shadow_data = (void *)((long)data + i * init->record_size);
+ }
+ }
+
+ /* Initialize records */
+ for(i=0; i<init->max_entries; i++)
+ {
+ bcmdb_entry *entry = (bcmdb_entry *)sor->entry.data + i;
+ entry->flags = BCMDB_FLAG_RECORD;
+ }
+ break;
+
+ default:
+ printf("Only array-based DB backend is supported\n");
+ bcmos_free(sor);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ /* Set locking callbacks based on locking policy */
+ switch(init->lock_policy)
+ {
+ case BCMDB_LOCK_SEM_READ_SEM_WRITE:
+ sor->lock_record_write = bcmdb_sem_read_sem_write_lock_write;
+ sor->lock_record_read = bcmdb_sem_read_sem_write_lock_read;
+ sor->unlock_record_write = bcmdb_sem_read_sem_write_unlock_write;
+ sor->unlock_record_read = bcmdb_sem_read_sem_write_unlock_read;
+ sor->lock_set_read = bcmdb_set_lock_read_sem;
+ sor->unlock_set_read = bcmdb_set_unlock_read_sem;
+ sor->lock_set_modify = bcmdb_set_lock_modify_sem;
+ sor->unlock_set_modify = bcmdb_set_unlock_modify_sem;
+ sor->lock_set_recursively_modify = bcmdb_set_lock_recursively_modify_sem ;
+ sor->unlock_set_recursively_modify = bcmdb_set_unlock_recursively_modify_sem ;
+ break;
+
+ case BCMDB_LOCK_NONE:
+ case BCMDB_LOCK_OTHER:
+ sor->lock_record_write = bcmdb_dummy_lock_write;
+ sor->lock_record_read = bcmdb_dummy_lock_read;
+ sor->unlock_record_write = bcmdb_dummy_unlock_write;
+ sor->unlock_record_read = bcmdb_dummy_unlock_read;
+ sor->lock_set_read = bcmdb_set_lock_read_dummy;
+ sor->unlock_set_read = bcmdb_set_unlock_read_dummy;
+ sor->lock_set_modify = bcmdb_set_lock_modify_dummy;
+ sor->unlock_set_modify = bcmdb_set_unlock_modify_dummy;
+ sor->lock_set_recursively_modify = bcmdb_set_lock_recursively_modify_dummy ;
+ sor->unlock_set_recursively_modify = bcmdb_set_unlock_recursively_modify_dummy ;
+ break;
+
+ case BCMDB_LOCK_NB_READ_SHADOW_WRITE:
+ sor->lock_record_write = bcmdb_nb_read_shadow_write_lock_write;
+ sor->lock_record_read = bcmdb_nb_read_shadow_write_lock_read;
+ sor->unlock_record_write = bcmdb_nb_read_shadow_write_unlock_write;
+ sor->unlock_record_read = bcmdb_nb_read_shadow_write_unlock_read;
+ sor->lock_set_read = bcmdb_set_lock_read__nb_read_sem_write;
+ sor->unlock_set_read = bcmdb_set_unlock_read__nb_read_sem_write;
+ sor->lock_set_modify = bcmdb_set_lock_modify__nb_read_sem_write;
+ sor->unlock_set_modify = bcmdb_set_unlock_modify__nb_read_sem_write;
+ sor->lock_set_recursively_modify = bcmdb_set_lock_recursively_modify_sem ;
+ sor->unlock_set_recursively_modify = bcmdb_set_unlock_recursively_modify_sem ;
+ break;
+
+ default:
+ printf("Lock policy %d is not supported\n", init->lock_policy);
+ if (data)
+ bcmos_free(data);
+ if (entries)
+ bcmos_free(entries);
+ bcmos_free(sor);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ /* create mutex_update */
+ rc = bcmos_mutex_create(&sor->mutex_update, init->os_flags);
+ if (rc)
+ {
+ if (data)
+ bcmos_free(data);
+ if (entries)
+ bcmos_free(entries);
+ bcmos_free(sor);
+ return BCM_ERR_NOMEM;
+ }
+
+ /* create sem_wait_read_to_finish. it is initialized to be taken */
+ rc = bcmos_sem_create(&sor->sem_wait_read_to_finish, 0, init->os_flags);
+ if (rc)
+ {
+ /* no point to check here the error code of bcmos_mutex_destroy */
+ bcmos_mutex_destroy(&sor->mutex_update);
+ if (data)
+ bcmos_free(data);
+ if (entries)
+ bcmos_free(entries);
+ bcmos_free(sor);
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmos_fastlock_init(&sor->fastlock, init->os_flags);
+
+ *new_set = sor;
+
+ return 0;
+}
+
+
+/** Lock data set for reading. When set is locked - it can't be
+ * modified.
+ *
+ * \param[in] set data base set to be locked
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_set_lock_read(bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!set->lock_set_read);
+ set->lock_set_read(set);
+}
+
+
+/** Release data set lock
+ *
+ * Unlock set locked by \ref bcmdb_set_lock_read
+ *
+ * \param[in] set data base set to be unlocked
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_set_unlock_read(bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!set->unlock_set_read);
+ set->unlock_set_read(set);
+}
+
+
+/** Lock data set for modify. If the set is SoS, the locking
+ * will be recursive.
+ *
+ * \param[in] set data base set to be locked
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_set_lock_modify(bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!set->lock_set_recursively_modify);
+ set->lock_set_recursively_modify(set);
+}
+
+
+/** Release data set lock
+ *
+ * Unlock set locked by \ref bcmdb_set_lock_modify
+ *
+ * \param[in] set data base set to be unlocked
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_set_unlock_modify(bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!set->unlock_set_recursively_modify);
+ set->unlock_set_recursively_modify(set);
+}
+
+
+/** Add set to the parent set with specific key.
+ *
+ * The function adds set to the parent set creating data base hierarchy.
+ * The function automatically acquires modify lock and releases it
+ * in the end of operation.
+ * \param[in] sos parent set of sets
+ * \param[in] key key to add new set at
+ * \param[in] new_set set control block
+ * \return
+ * =0 - OK\n
+ * <0 - error code
+ * \ingroup bcmdb
+ */
+int bcmdb_set_add(bcmdb_set *sos, bcmdb_key key, bcmdb_set *new_set)
+{
+ int rc;
+ long fastlock_flags;
+ BUG_ON(!sos);
+ BUG_ON(!sos->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sos->entry.flags & BCMDB_FLAG_SOS));
+ BUG_ON(!new_set);
+ BUG_ON(!new_set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!new_set->my_key == BCMDB_KEY_INVAL);
+ fastlock_flags = sos->lock_set_modify(sos);
+ rc = sos->entry_new(sos, key, new_set);
+ sos->unlock_set_modify(sos, fastlock_flags);
+ return rc;
+}
+
+
+/** Get set handle given its key.
+ *
+ * \param[in] sos parent set of sets
+ * \param[in] key set key.
+ * \return
+ * !=0 - set handle
+ * NULL- doesn't exist
+ * \ingroup bcmdb
+ */
+bcmdb_set *bcmdb_set_handle(const bcmdb_set *sos, bcmdb_key key)
+{
+ bcmdb_entry *entry;
+ BUG_ON(!sos);
+ BUG_ON(!sos->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sos->entry.flags & BCMDB_FLAG_SOS));
+ entry = sos->key_to_handle(sos, key);
+ if (!entry || !(entry->flags & BCMDB_FLAG_VALID))
+ return NULL;
+ return (bcmdb_set *)entry->data;
+}
+
+
+/** Get set key given its handle.
+ *
+ * \param[in] set set handle
+ * \param[in] key set key.
+ * \return
+ * !=BCMDB_KEY_INVAL - set key
+ * BCMDB_KEY_INVAL - error
+ * \ingroup bcmdb
+ */
+bcmdb_key bcmdb_set_key(const bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ return set->my_key;
+}
+
+
+/** Get set name
+ *
+ * \param[in] set set handle
+ * \return set name
+ * \ingroup bcmdb
+ */
+const char *bcmdb_set_name(const bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ return set->name;
+}
+
+
+/** Get number of records in the set.
+ *
+ * \param[in] set set handle
+ * \return number of active records in the set
+ * \ingroup bcmdb
+ */
+int bcmdb_set_num_records(const bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ return set->num_entries;
+}
+
+
+/** Get entry size
+ *
+ * \param[in] set set handle
+ * \return set entry size
+ * \ingroup bcmdb
+ */
+int bcmdb_set_entry_size(const bcmdb_set *set)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ return set->entry_size;
+}
+
+
+/** Add record to the parent set with specific key.
+ *
+ * The function creates a new record and adds it to the parent set with specific key.
+ * The function automatically acquires modify lock and releases it
+ * in the end of operation.
+ * \param[in] sor parent set of records
+ * \param[in] key key to add new set at
+ * \param[in] data record data. Data size is defined at parent SOR registration time.
+ * \param[out] p_record new record handle
+ * \return
+ * =0 - OK\n
+ * <0 - error code
+ * \ingroup bcmdb
+ */
+int bcmdb_record_add(bcmdb_set *sor, bcmdb_key key, const void *data)
+{
+ int rc;
+ long fastlock_flags;
+
+ BUG_ON(!sor);
+ BUG_ON(!data);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+
+ fastlock_flags = sor->lock_set_modify(sor);
+ rc=sor->entry_new(sor, key, data);
+ sor->unlock_set_modify(sor, fastlock_flags);
+ return rc;
+}
+
+
+/** Delete record from the parent SoR given the record key.
+ *
+ * The function automatically acquires modify lock and releases it
+ * in the end of operation.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key.
+ */
+void bcmdb_record_delete(bcmdb_set *sor, bcmdb_key key)
+{
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+
+ sor->lock_record_write(sor, key, 1);
+ sor->unlock_record_write(sor, 1, 0);
+}
+
+
+/** Get record data pointer without locking.
+ *
+ * The function returns pointer to data structure stored in data base record.\n
+ * Attention! The caller is required to aquire read or write lock - as appropriate
+ * before calling this function and release the lock when processing is finished.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \return
+ * data pointer. NULL if there is no record matching the key.
+ * \ingroup bcmdb
+ */
+void *bcmdb_record_getraw_nolock(bcmdb_set *sor, bcmdb_key key)
+{
+ bcmdb_entry *entry;
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+ entry = sor->key_to_handle(sor, key);
+ if (!entry || !(entry->flags & BCMDB_FLAG_VALID))
+ return NULL;
+ return entry->data;
+}
+
+
+/** Lock record for reading and return record data pointer.
+ *
+ * The function aquires read-lock and returns pointer to data structure stored in data base record.\n
+ * read-lock must be released separately when the pointer is no longer in use.
+ * Note that the default record-read lock is non-blocking and counting.
+ * That means that multiple processes cam read-lock the same record without blocking.
+ * The function is low-level. It is recommended to use macro \ref bcmdb_record_get_read instead.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \return
+ * data pointer. NULL if there is no record matching the key.
+ * \ingroup bcmdb
+ */
+const void *bcmdb_record_getraw_read(bcmdb_set *sor, bcmdb_key key)
+{
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+ return sor->lock_record_read(sor, key);
+}
+
+
+/** Unlock record locked for reading.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_record_unlock_read(bcmdb_set *sor, bcmdb_key key)
+{
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+ sor->unlock_record_read(sor, key);
+}
+
+
+/** Read record data into user area.
+ *
+ * The function aquires read-lock, reads data into user area and releases read-lock.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[in] offset offset in data record
+ * \param[in] size data size. Note that offset+size must be <= record_size
+ * \param[in] data data pointer.
+ * \return
+ * =0-OK\n
+ * <0-error code
+ * \ingroup bcmdb
+ */
+int bcmdb_record_read(bcmdb_set *sor, bcmdb_key key, int offset, int size, void *data)
+{
+ const void *d = bcmdb_record_getraw_read(sor, key);
+ if (!d)
+ return BCM_ERR_PARM;
+ if ((unsigned)offset + (unsigned)size > sor->entry_size)
+ {
+ bcmdb_record_unlock_read(sor, key);
+ return BCM_ERR_PARM;
+ }
+ memcpy(data, (const char *)d+(unsigned)offset, (unsigned)size);
+ bcmdb_record_unlock_read(sor, key);
+ return 0;
+}
+
+
+/** Lock record for writing and return record data pointer.
+ *
+ * The function aquires write-lock and returns pointer to data structure stored in data base record.\n
+ * write-lock must be released separately when the pointer is no longer in use.
+ * The function is low-level. It is recommended to use macro \ref bcmdb_record_get_write instead.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \return
+ * data pointer. NULL if there is no record matching the key.
+ * \ingroup bcmdb
+ */
+void *bcmdb_record_getraw_write(bcmdb_set *sor, bcmdb_key key)
+{
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+ return sor->lock_record_write(sor, key, 0);
+}
+
+
+/** Unlock record locked for writing.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] is_cancellation TRUE=cancel transaction
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_record_unlock_write(bcmdb_set *sor, int is_cancellation)
+{
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!(sor->entry.flags & BCMDB_FLAG_SOS)==0);
+ sor->unlock_record_write(sor, 0, is_cancellation);
+}
+
+
+/** Write record data.
+ *
+ * The function aquires modify-lock, replaces data stored in data base record
+ * and releses the lock.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[in] offset offset in data record
+ * \param[in] size data size. Note that offset+size must be <= record_size
+ * \param[in] data data pointer.
+ * \return
+ * =0-OK\n
+ * <0-error code
+ * \ingroup bcmdb
+ */
+int bcmdb_record_write(bcmdb_set *sor, bcmdb_key key, int offset, int size, const void *data)
+{
+ void *d=bcmdb_record_getraw_write(sor, key);
+ if (!d)
+ return BCM_ERR_PARM;
+ if ((unsigned)offset + (unsigned)size > sor->entry_size)
+ {
+ bcmdb_record_unlock_write(sor, 0);
+ return BCM_ERR_PARM;
+ }
+ memcpy((char *)d+(unsigned)offset, data, (unsigned)size);
+ bcmdb_record_unlock_write(sor, 0);
+ return 0;
+}
+
+
+/** Register notification function to get informed
+ * when data base set is modified.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] cb callback function pointer
+ * \param[in] cb_priv private data that should be passed to the callback
+ * \return
+ * =0 - OK\n
+ * <0 - error code
+ * \ingroup bcmdb
+ */
+int bcmdb_set_notify_register(bcmdb_set *sor, bcmdb_notify_cb cb, long cb_priv)
+{
+ bcmdb_notify *nf_new, *nf, *nf_prev = NULL;
+
+ BUG_ON(!sor);
+ BUG_ON(!sor->magic == BCMDB_MAGIC_ACTIVE_SET);
+ BUG_ON(!cb);
+
+ nf_new = bcmos_calloc(sizeof(bcmdb_notify));
+ if (!nf_new)
+ return BCM_ERR_NOMEM;
+ nf_new->cb = cb;
+ nf_new->cb_priv = cb_priv;
+
+ /* Add to set's notification list */
+ nf = sor->notify_list_head;
+ while(nf)
+ {
+ nf_prev = nf;
+ nf = nf->next;
+ }
+ if (nf_prev)
+ nf_prev->next = nf_new;
+ else
+ sor->notify_list_head = nf_new;
+
+ return 0;
+}
+
+
+/** Data base iterator
+ *
+ * \param[in] set data base set
+ * \param[in] prev last entry. BCMDB_KEY_ANY=start from the beginning
+ * \return data base entry key following prev or BCMDB_KEY_NO_MORE if end is reached.\n
+ * BCMDB_KEY_INVAL is reqturned if prev key is invalid
+ * \ingroup bcmdb
+ */
+bcmdb_key bcmdb_set_iterate(const bcmdb_set *set, bcmdb_key prev)
+{
+ BUG_ON(!set);
+ BUG_ON(!set->magic == BCMDB_MAGIC_ACTIVE_SET);
+ return set->entry_get_next(set, prev);
+}
+
+
+/* Print database structure */
+static void _bcmdb_print_structure(const bcmdb_set *set, int level)
+{
+ int i;
+
+ if (!set)
+ return;
+
+ /* Indentation */
+ for(i=0; i<level; i++)
+ printf("\t");
+
+ if ((set->entry.flags & BCMDB_FLAG_SOS))
+ {
+ bcmdb_key key = bcmdb_set_iterate(set, BCMDB_KEY_ANY);
+ printf("%-16s SoS max_entries=%d entries=%d\n", set->name, set->max_entries, set->num_entries);
+ while(key >= 0)
+ {
+ _bcmdb_print_structure(bcmdb_set_handle(set, key), level+1);
+ key = bcmdb_set_iterate(set, key);
+ }
+ }
+ else
+ {
+ printf("%-16s SoR max_entries=%d entries=%d record_size=%d total_size=%d\n",
+ set->name, set->max_entries, set->num_entries, set->entry_size,
+ set->entry_size*set->max_entries);
+ }
+}
+
+
+/** Print database structure.
+ *
+ * \param[in] set root set
+ * \ingroup bcmdb
+ */
+void bcmdb_set_print_structure(const bcmdb_set *set)
+{
+ _bcmdb_print_structure(set, 0);
+}
+
+
+/** Format record for printing.
+ *
+ * The function converts record data to human-readible format.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[out] buffer output buffer
+ * \param[in] size buffer size
+ * \return
+ * >=0-amount of data placed in the buffer\n
+ * <0-error code
+ */
+int bcmdb_record_read_formatted(bcmdb_set *sor, bcmdb_key key, char *buffer, int size)
+{
+ const void *data;
+ int len;
+ if (!buffer || !size)
+ return BCM_ERR_PARM;
+ if (!sor->format)
+ return BCM_ERR_NOT_SUPPORTED;
+ *buffer=0;
+ data = bcmdb_record_getraw_read(sor, key);
+ if (!data)
+ return 0;
+ len = sor->format(data, buffer, size);
+ bcmdb_record_unlock_read(sor, key);
+ return len;
+}
diff --git a/bal_release/src/common/db_engine/bcm_db_engine.h b/bal_release/src/common/db_engine/bcm_db_engine.h
new file mode 100644
index 0000000..8d77022
--- /dev/null
+++ b/bal_release/src/common/db_engine/bcm_db_engine.h
@@ -0,0 +1,622 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/*
+ * bcm_db_engine.c
+ *
+ * Data base engine
+ */
+#ifndef BCMDB_ENGINE_H
+
+#define BCMDB_ENGINE_H
+
+/** \defgroup bcmdb_e Data Base Engine Module
+Hierarchical data base is built from 3 types of objects:
+- set: consists of control info and dynamic array of other sets OR of records of the same kind.
+ - Mixing subsets and records in the same set is not supported.
+ - Sets are objects that perform operations like access, locking, adding or removing elements,
+ etc., via methods that can differ for every set.
+ - Set elements are addressed using a single key.
+ - Most sets are internally organized as arrays. However, other organizations (e.g., lists, hash tables)
+ are also possible because each set can have different set of methods for element access.
+- record: is a container for storing information.
+ - Record consists of control info and a structure containing fields.
+ - Record is the smallest DB element that has a handle and can be individually locked.
+ - Record size is fixed at time when the set containing records is created.
+- field: is a convenience element.
+ - DB API includes field access macros for convenience and traceability.
+ Apart from that, record layout is transparent to the DB engine.
+ - DB user has an option of accessing record fields directly (as C structure fields), without using DB API
+ @{
+*/
+
+#define bcmdb_error_print(rc,format,args...) BCMOS_TRACE_ERR("status:%s :" format, bcmos_strerror(rc), ##args)
+
+/** Data base backend type
+ */
+typedef enum
+{
+ BCMDB_BACKEND_ARRAY, /**< Array-based backend */
+ BCMDB_BACKEND_HASH, /**< Hash-based backend */
+ BCMDB_BACKEND_OTHER /**< User-defined backend */
+} bcmdb_backend_type;
+
+
+/** Data locking policy
+ */
+typedef enum
+{
+ BCMDB_LOCK_NONE, /**< No record-level locking. Can be used for records containing independent fields */
+ BCMDB_LOCK_NB_READ_SHADOW_WRITE,/**< Non-blocking read, write using shadow area (default) */
+ BCMDB_LOCK_SEM_READ_SEM_WRITE, /**< Strong locking. Both read and write locks use semaphores */
+ BCMDB_LOCK_OTHER /**< User-defined locking policy */
+} bcmdb_lock_policy;
+
+
+/** Data base key
+ * Valid values >= 0
+ */
+typedef int bcmdb_key;
+
+
+/** Any key
+ */
+#define BCMDB_KEY_ANY (-1)
+
+/** Invalid key
+ */
+#define BCMDB_KEY_INVAL (-2)
+
+/** No more records
+ */
+#define BCMDB_KEY_NO_MORE (-3)
+
+
+ /** Data Base Set control block */
+typedef struct bcmdb_set bcmdb_set;
+
+/** Data Base Record control block */
+typedef struct bcmdb_record bcmdb_record;
+
+/** Data Base Set or Record */
+typedef struct bcmdb_entry bcmdb_entry;
+
+
+/** Data base operations for notifications.
+ */
+typedef enum
+{
+ BCMDB_OPER_ADD, /**< Entry has been added */
+ BCMDB_OPER_DELETE, /**< Entry has been deleted */
+ BCMDB_OPER_UPDATE /**< Entry has been modified */
+} bcmdb_oper_t;
+
+
+/** Data base update notification callback.
+ */
+typedef void (*bcmdb_notify_cb)(bcmdb_set *set, bcmdb_key key, bcmdb_oper_t oper, void *new_data);
+
+
+/** Format callback. Used by bcmdb_record_read_formatted to convert record data to human-readible format */
+typedef int (*bcmdb_format_cb)(const void *data, char *buffer, int buffer_size);
+
+
+/** Set-of-Sets init structure.
+ */
+typedef struct bcmdb_sos_init
+{
+ const char *name; /**< Set name */
+ bcmdb_backend_type backend_type; /**< Backend type */
+ uint32_t max_entries; /**< Max number of entries. 0=unlimited (not supported for array backend) */
+ uint32_t os_flags; /**< OS flags. Control whether set can be accessed by multiple cores. See bcmos_mutex_create() */
+} bcmdb_sos_init;
+
+
+/** Set-of-Records init structure.
+ */
+typedef struct bcmdb_sor_init
+{
+ const char *name; /**< Set name */
+ bcmdb_backend_type backend_type; /**< Backend type */
+ bcmdb_lock_policy lock_policy; /**< Set locking policy */
+ uint32_t max_entries; /**< Max number of entries. 0=unlimited (not supported for array backend) */
+ uint32_t record_size; /**< Record size > 0 */
+ bcmdb_format_cb format; /**< callback that converts record data to human-readable form */
+ uint32_t os_flags; /**< OS flags. Control whether set can be accessed by multiple cores. See bcmos_mutex_create() */
+} bcmdb_sor_init;
+
+
+/** Initialize data base engine
+ *
+ * \return
+ * 0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_module_init(void);
+
+
+/** Make set-of-sets control block.
+ *
+ * Helper function that creates a set of sets with reasonable defaults for all callbacks and fields.
+ * Once created, the set control block can be tuned before adding the new set to its parent set.
+ * \param[in] init set parameters
+ * \param[out] new_set set control block
+ * \return
+ * 0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_make_set_of_sets(const bcmdb_sos_init *init, bcmdb_set **new_set);
+
+
+/** Make set-of-sets control block macro.
+ *
+ * Calls \ref bcmdb_make_set_of_sets.
+ * Prints error message and jumps to error_label in case of failure.
+ * For parameter description see \ref bcmdb_make_set_of_sets
+ */
+#define BCMDB_MAKE_SOS(_name,_backend,_max_entries,_p_handle,_rc,_error_label) \
+({\
+ bcmdb_sos_init _init = { .name=_name, .max_entries=_max_entries, .backend_type=_backend};\
+ _rc = bcmdb_make_set_of_sets(&_init, _p_handle);\
+ if (_rc)\
+ {\
+ bcmdb_error_print(_rc, "failed to create set %s.\n", _name);\
+ goto _error_label;\
+ }\
+})
+
+
+/** Make set-of-records control block.
+ *
+ * Helper function that creates a set of records with reasonable defaults for all callbacks and fields.
+ * Once created, the set control block can be tuned before adding the new set to its parent set.
+ * \param[in] init set parameters
+ * \param[in] alloc_records true (1) - allocate memory for all records.
+ * \param[out] new_set set control block
+ * \return
+ * 0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_make_set_of_records(const bcmdb_sor_init *init, int alloc_records, bcmdb_set **new_set);
+
+
+/** Make set-of-records control block macro.
+ *
+ * Calls \ref bcmdb_make_set_of_records.
+ * Prints error message and jumps to error_label in case of failure.
+ * For parameter description see \ref bcmdb_make_set_of_records
+ */
+#define BCMDB_MAKE_SOR(_name,_backend,_lock,_max_entries,_rec_size,_is_alloc,_format,_p_handle,_rc,_error_label) \
+({\
+ bcmdb_sor_init _init = { .name=_name, .max_entries=_max_entries, .backend_type=_backend,\
+ .lock_policy=_lock, .record_size=_rec_size,.format=_format};\
+ _rc = bcmdb_make_set_of_records(&_init,_is_alloc,_p_handle);\
+ if (_rc)\
+ {\
+ bcmdb_error_print(_rc, "failed to create record set %s.\n", _name);\
+ goto _error_label;\
+ }\
+})
+
+
+/** Lock data set. When set is locked - it can't be modified.
+ *
+ * \param[in] set data base set to be locked
+ *
+ */
+void bcmdb_set_lock_read(bcmdb_set *set);
+
+
+/** Release data set lock
+ *
+ * Unlock set locked by \ref bcmdb_set_lock_read
+ *
+ * \param[in] set data base set to be unlocked
+ */
+void bcmdb_set_unlock_read(bcmdb_set *set);
+
+
+/** Lock data set for modify. If the set is SoS, the locking
+ * will be recursive.
+ *
+ * \param[in] set data base set to be locked
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_set_lock_modify(bcmdb_set *set);
+
+
+/** Release data set lock
+ *
+ * Unlock set locked by \ref bcmdb_set_lock_modify
+ *
+ * \param[in] set data base set to be unlocked
+ *
+ * \ingroup bcmdb
+ */
+void bcmdb_set_unlock_modify(bcmdb_set *set);
+
+
+/** Add set to the parent set.
+ *
+ * The function adds set to the parent set creating data base hierarchy.
+ * The function automatically acquires modify lock and releases it
+ * in the end of operation.
+ * \param[in] sos parent set of sets
+ * \param[in] key key to add new set at
+ * \param[in] new_set set control block
+ * \return
+ * =0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_set_add(bcmdb_set *sos, bcmdb_key key, bcmdb_set *new_set);
+
+
+/** Add set to the parent set with specific key macro.
+ *
+ * Calls \ref bcmdb_set_add.
+ * Prints error message and jumps to error_label in case of failure.
+ * For parameter description see \ref bcmdb_set_add
+ */
+#define BCMDB_SET_ADD(_parent,_key,_set,_rc,_error_label) \
+({\
+ _rc = bcmdb_set_add(_parent,_key,_set);\
+ if (_rc)\
+ {\
+ bcmdb_error_print(_rc, "failed to add set %s to %s.\n", bcmdb_set_name(_set), bcmdb_set_name(_parent));\
+ goto _error_label;\
+ }\
+})
+
+
+/** Get set handle given its key.
+ *
+ * \param[in] sos parent set of sets
+ * \param[in] key set key.
+ * \return
+ * !=0 - set handle
+ * NULL- doesn't exist
+ */
+bcmdb_set *bcmdb_set_handle(const bcmdb_set *sos, bcmdb_key key);
+
+
+/** Get set key given its handle.
+ *
+ * \param[in] set set handle
+ * \return
+ * !=BCMDB_KEY_INVAL - set key\n
+ * BCMDB_KEY_INVAL - error
+ */
+bcmdb_key bcmdb_set_key(const bcmdb_set *set);
+
+
+/** Get set name
+ *
+ * \param[in] set set handle
+ * \return set name
+ */
+const char *bcmdb_set_name(const bcmdb_set *set);
+
+
+/** Get number of records in the set.
+ *
+ * \param[in] set set handle
+ * \return number of active records in the set
+ */
+int bcmdb_set_num_records(const bcmdb_set *set);
+
+
+/** Get entry size
+ *
+ * \param[in] set set handle
+ * \return set entry size
+ */
+int bcmdb_set_entry_size(const bcmdb_set *set);
+
+
+/** Add record to the parent set.
+ *
+ * The function creates a new record and adds it to the parent set with specific key.
+ * The function automatically acquires modify lock and releases it
+ * in the end of operation.
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[in] data record data. Data size is defined at parent SOR registration time.
+ * \return
+ * =0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_record_add(bcmdb_set *sor, bcmdb_key key, const void *data);
+
+
+/** Delete record from the parent SoR given the record key.
+ *
+ * The function automatically acquires modify lock and releases it
+ * in the end of operation.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key.
+ */
+void bcmdb_record_delete(bcmdb_set *sor, bcmdb_key key);
+
+
+/** Get record data pointer without locking.
+ *
+ * The function returns pointer to data structure stored in data base record.\n
+ * Attention! The caller is required to aquire read or write lock - as appropriate
+ * before calling this function and release the lock when processing is finished.
+ * The function is low-level. It is recommended to use \ref bcmdb_record_get_nolock instead.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \return
+ * data pointer. NULL if there is no record matching the key.
+ */
+void *bcmdb_record_getraw_nolock(bcmdb_set *sor, bcmdb_key key);
+
+
+/** Get record data pointer without locking.
+ *
+ * The function returns pointer to data structure stored in data base record.\n
+ * Attention! The caller is required to aquire read or write lock - as appropriate
+ * before calling this function and release the lock when processing is finished.
+ *
+ * \param[in] _sor parent set of records
+ * \param[in] _key record key
+ * \param[in] _record_type underlying data type.
+ * \return
+ * data pointer casted to the underlying data type\n
+ * NULL if there is no record matching the key.
+ */
+#define bcmdb_record_get_nolock(_sor, _key, _record_type) \
+ ({ \
+ assert(sizeof(_record_type)==bcmdb_set_entry_size(_sor)); \
+ (_record_type *)bcmdb_record_getraw_nolock(_sor, _key); \
+ })
+
+
+/** Lock record for reading and return record data pointer.
+ *
+ * The function aquires read-lock and returns pointer to data structure stored in data base record.\n
+ * read-lock must be released separately when the pointer is no longer in use.
+ * Note that the default record-read lock is non-blocking and counting.
+ * That means that multiple processes can read-lock the same record without blocking.
+ * The function is low-level. It is recommended to use macro \ref bcmdb_record_get_read instead.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \return
+ * data pointer. NULL if there is no record matching the key.
+ */
+const void *bcmdb_record_getraw_read(bcmdb_set *sor, bcmdb_key key);
+
+
+/** Lock record for reading and return record data pointer.
+ *
+ * The macro returns pointer to data structure stored in data base record.\n
+ * The read-lock must be released separately when the pointer is no longer in use.
+ * Note that the default record-read lock is non-blocking and counting.
+ * That means that multiple processes can read-lock the same record without blocking.
+ *
+ * \param[in] _sor parent set of records
+ * \param[in] _key record key
+ * \param[in] _record_type underlying data type.
+ * \return
+ * data pointer casted to the underlying data type
+ */
+#define bcmdb_record_get_read(_sor, _key, _record_type) \
+ ({ \
+ assert(sizeof(_record_type)==bcmdb_set_entry_size(_sor)); \
+ (const _record_type *)bcmdb_record_getraw_read(_sor, _key);\
+ })
+
+
+/** Unlock record locked for reading.
+ *
+ * This function must be called after \ref bcmdb_record_get_read or
+ * \ref bcmdb_record_getraw_read. Following bcmdb_record_read_unlock
+ * call pointer returned by \ref bcmdb_record_get_read becomes invalid.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ *
+ */
+void bcmdb_record_unlock_read(bcmdb_set *sor, bcmdb_key key);
+
+
+/** Read record data into user area.
+ *
+ * The function aquires read-lock, reads data into user area and releases read-lock.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[in] offset offset in data record
+ * \param[in] size data size. Note that offset+size must be <= record_size
+ * \param[in] data data pointer.
+ * \return
+ * =0-OK\n
+ * <0-error code
+ */
+int bcmdb_record_read(bcmdb_set *sor, bcmdb_key key, int offset, int size, void *data);
+
+
+/** Get record field.
+ *
+ * The macro returns record field value.
+ *
+ * \param[in] _sor parent set of records
+ * \param[in] _key record key
+ * \param[in] _record_type type of the underlying data structure.
+ * \param[in] _field_name data structure field name
+ * \param[out] _p_field_value pointer of variable where data structure field value should be returned
+ * \return
+ * =0-OK\n
+ * <0-error code
+ */
+#define bcmdb_record_read_field(_sor, _key, _record_type, _field_name, _p_field_value) \
+ bcmdb_record_read(_sor, _key, offsetof(_record_type, _field_name), \
+ sizeof(*(_p_field_value)), _p_field_value);
+
+
+/** Lock record for writing and return record data pointer.
+ *
+ * The function aquires write-lock and returns pointer to data structure stored in data base record.\n
+ * write-lock must be released separately when the pointer is no longer in use.
+ * The function is low-level. It is recommended to use macro \ref bcmdb_record_get_write instead.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \return
+ * data pointer. NULL if there is no record matching the key.
+ */
+void *bcmdb_record_getraw_write(bcmdb_set *sor, bcmdb_key key);
+
+
+/** Lock record for writing and return record data pointer.
+ *
+ * The function aquires write-lock and returns pointer to data structure stored in data base record.\n
+ * write-lock must be released separately when the pointer is no longer in use.
+ *
+ * \param[in] _sor parent set of records
+ * \param[in] _key record key
+ * \param[in] _record_type underlying data type.
+ * \return
+ * data pointer casted to the underlying data type
+ */
+#define bcmdb_record_get_write(_sor, _key, _record_type) \
+ ({ \
+ assert(sizeof(_record_type)==bcmdb_set_entry_size(_sor)); \
+ (_record_type *)bcmdb_record_getraw_write(_sor, _key);\
+ })
+
+
+/** Unlock record locked for writing.
+ *
+ * This function must be called after \ref bcmdb_record_get_write or
+ * \ref bcmdb_record_getraw_write. Following bcmdb_record_unlock_write
+ * call pointer returned by \ref bcmdb_record_get_write becomes invalid.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] is_cancellation TRUE=cancel transaction
+ *
+ */
+void bcmdb_record_unlock_write(bcmdb_set *sor, int is_cancellation);
+
+
+
+/** Write record data.
+ *
+ * The function aquires modify-lock, replaces data stored in data base record
+ * and releses the lock.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[in] offset offset in data record
+ * \param[in] size data size. Note that offset+size must be <= record_size
+ * \param[in] data data pointer.
+ * \return
+ * =0-OK\n
+ * <0-error code
+ */
+int bcmdb_record_write(bcmdb_set *sor, bcmdb_key key, int offset, int size, const void *data);
+
+
+/** Write record field.
+ *
+ * The macro updates record field value.\n
+ * The macro aquires and releases record-modify lock.
+ *
+ * \param[in] _sor parent set of records
+ * \param[in] _key record key
+ * \param[in] _record_type type of the underlying data structure.
+ * \param[in] _field_name data structure field name
+ * \param[in] _field_value field value
+ * \return
+ * =0-OK\n
+ * <0-error code
+ */
+#define bcmdb_record_write_field(_sor, _key, _record_type, _field_name, _field_value) \
+ ({ \
+ typeof(((_record_type *)0)->_field_name) _f = _field_value;\
+ bcmdb_record_write(_sor, _key, offsetof(_record_type, _field_name), sizeof(_f), &_f);\
+ });
+
+
+/** Register notification function to get informed
+ * when data base set is modified.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] cb callback function pointer
+ * \param[in] cb_priv private data that should be passed to the callback
+ * \return
+ * =0 - OK\n
+ * <0 - error code
+ */
+int bcmdb_set_notify_register(bcmdb_set *sor, bcmdb_notify_cb cb, long cb_priv);
+
+
+/** Data base iterator
+ *
+ * \param[in] set data base set
+ * \param[in] prev last entry. BCMDB_KEY_ANY=start from the beginning
+ * \return data base entry key following prev or BCMDB_KEY_NO_MORE if end is reached.\n
+ * BCMDB_KEY_INVAL is reqturned if prev key is invalid
+ */
+bcmdb_key bcmdb_set_iterate(const bcmdb_set *set, bcmdb_key prev);
+
+
+/** Print database structure.
+ *
+ * \param[in] set root set
+ */
+void bcmdb_set_print_structure(const bcmdb_set *set);
+
+
+/** Format record for printing.
+ *
+ * The function converts record data to human-readable format.
+ *
+ * \param[in] sor parent set of records
+ * \param[in] key record key
+ * \param[out] buffer output buffer
+ * \param[in] size buffer size
+ * \return
+ * >=0-amount of data placed in the buffer\n
+ * <0-error code
+ */
+int bcmdb_record_read_formatted(bcmdb_set *sor, bcmdb_key key, char *buffer, int size);
+
+
+/** @} end of bcmdb_e group */
+
+
+#endif /* #ifndef BCMDB_ENGINE_H */
+
diff --git a/bal_release/src/common/db_engine/unitest.c b/bal_release/src/common/db_engine/unitest.c
new file mode 100644
index 0000000..ca638ce
--- /dev/null
+++ b/bal_release/src/common/db_engine/unitest.c
@@ -0,0 +1,490 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/*
+ * unitest.c
+ *
+ * Created on: 2013-12-10
+ * Author: swallace
+ */
+
+#include "bcmos_system.h"
+#include "bcm_db_engine.h"
+
+/* EPON LLID data structure subset */
+typedef enum
+ {
+ /* Free entry in the LLID management table, available for assignment on an
+ MPCP register request. */
+ unassigned_llid,
+ /* Locked out waiting on a timer to release the LLID */
+ not_registered_llid,
+ /* Waiting for permission to register from host */
+ ignored_llid,
+ /* LLID has been assigned to an ONU MAC but not registered. Intermediate
+ state before the ONU returns a registration ack. */
+ wait_reg_ack_llid,
+ /* OLT link is in-service; user traffic is allowed */
+ inservice_llid,
+ wait_no_reports_llid,
+ /* The following state only applies to multicast/flood links */
+ in_service_mcast_llid,
+ /* We want a "Reserved" state for things like Optical monitoring */
+ reserved_llid,
+ /* We have detected a rogue ONU on this LLID - don't use it! */
+ quarantined_llid,
+ llid_state_count,
+ } epon_olt_llid_state;
+
+static char *get_llid_state_string(epon_olt_llid_state llid_state)
+{
+ static char *llid_state_strings[]= {
+ "unassigned",
+ "not_registered",
+ "ignored",
+ "wait_reg_ack",
+ "inservice",
+ "wait_no_reports",
+ "in_service_mcast",
+ "reserved",
+ "quarantined"
+ };
+
+ return llid_state_strings[(uint16_t)(llid_state)];
+}
+
+#define MAX_LINKS_PER_PORT 512
+#define MAX_PORTS_PER_HALF_CHIP 8
+#define MAX_LINKS_PER_HALF_CHIP ((MAX_LINKS_PER_PORT)*(MAX_PORTS_PER_HALF_CHIP))
+
+typedef uint8_t core_epon;
+typedef uint16_t hw_link_index;
+
+typedef struct epon_db_olt_llid_rec
+ {
+ epon_olt_llid_state state;
+ core_epon epon;
+ hw_link_index index;
+ } epon_db_olt_llid_rec;
+
+
+typedef struct epon_msg_olt_llid_rec
+{
+ uint16_t index;
+ epon_db_olt_llid_rec llid_rec;
+} epon_msg_olt_llid_rec;
+
+typedef enum
+ {
+ enabled,
+ disabled,
+ } epon_olt_port_state;
+
+static char *get_port_state_string(epon_olt_port_state port_state)
+{
+ static char *port_state_strings[]= {
+ "enabled",
+ "disabled",
+ };
+
+ return port_state_strings[(uint16_t)(port_state)];
+}
+
+
+typedef struct epon_db_olt_port_rec
+ {
+ epon_olt_port_state state;
+ } epon_db_olt_port_rec;
+
+typedef struct epon_msg_olt_port_rec
+{
+ uint16_t index;
+ epon_db_olt_port_rec port_rec;
+} epon_msg_olt_port_rec;
+
+typedef enum
+{
+ epon_olt_link_record,
+ epon_olt_port_record,
+ num_db_tables,
+} db_tables;
+
+
+/* Master database handle */
+static bcmdb_set *db_sos_set;
+
+static bcmdb_set* epon_get_db_handle(void)
+{
+ return db_sos_set;
+}
+
+#define LINK_REC_DB() bcmdb_set *db_set = bcmdb_set_handle(epon_get_db_handle(), epon_olt_link_record)
+
+#define PORT_REC_DB bcmdb_set *db_set = bcmdb_set_handle(epon_get_db_handle(), epon_olt_port_record)
+
+/* Database test messages - */
+typedef enum
+ {
+ update_link_db = 20,
+ update_port_db = 21,
+ dump_db = 30,
+ } dbtest_msgid;
+
+static inline const epon_db_olt_llid_rec *epon_olt_get_llid_rec_read(uint16_t index)
+ {
+ LINK_REC_DB();
+ return bcmdb_record_get_read(db_set, index, epon_db_olt_llid_rec);
+ };
+
+static inline void epon_db_olt_unlock_llid_rec(uint16_t index)
+ {
+ LINK_REC_DB();
+ bcmdb_record_unlock_read(db_set, index);
+ }
+
+
+#define OltGetLlidRecWrite(index) \
+ ({ \
+ LINK_REC_DB(); \
+ bcmdb_record_get_write(db_set, index, epon_db_olt_llid_rec);\
+ })
+
+#define OltCommitLlidRec(index) \
+ ({ \
+ LINK_REC_DB(); \
+ bcmdb_record_unlock_write(db_set, BCMOS_FALSE);\
+ })
+
+
+static void ut_dump_db(void)
+{
+ uint16_t index;
+ bcmdb_set *db_set;
+
+ db_set = bcmdb_set_handle(epon_get_db_handle(), epon_olt_port_record);
+ for (index = 0; index < MAX_PORTS_PER_HALF_CHIP; index++)
+ {
+ const epon_db_olt_port_rec *port_rec;
+ port_rec = bcmdb_record_get_read(db_set, index, epon_db_olt_port_rec);
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO,
+ "Record %d, state %s\n", index,
+ get_port_state_string(port_rec->state));
+ bcmdb_record_unlock_read(db_set, index);
+ }
+
+ for (index = 0; index < MAX_LINKS_PER_HALF_CHIP; index++)
+ {
+ const epon_db_olt_llid_rec *llid_rec;
+ llid_rec = epon_olt_get_llid_rec_read(index);
+ if (llid_rec->state != unassigned_llid)
+ {
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO,
+ "Record %d, port %d, state %s\n", llid_rec->index,
+ llid_rec->epon, get_llid_state_string(llid_rec->state));
+ }
+ epon_db_olt_unlock_llid_rec(index);
+ }
+
+
+}
+
+static void ut_update_link_db(epon_msg_olt_llid_rec *rec)
+{
+ epon_db_olt_llid_rec *llid_rec;
+ llid_rec=OltGetLlidRecWrite(rec->index);
+ llid_rec->state=rec->llid_rec.state;
+
+ OltCommitLlidRec(index);
+}
+
+static void ut_update_port_db(epon_msg_olt_port_rec *rec)
+{
+ bcmdb_set *db_set;
+ epon_db_olt_port_rec *port_rec;
+
+ db_set = bcmdb_set_handle(epon_get_db_handle(), epon_olt_port_record);
+ port_rec = bcmdb_record_get_write(db_set, rec->index, epon_db_olt_port_rec);
+
+ port_rec->state=rec->port_rec.state;
+
+ bcmdb_record_unlock_write(db_set, BCMOS_FALSE);
+}
+
+
+static void ut_msg_handler(dbtest_msgid id, void *data)
+ {
+ switch (id)
+ {
+ case update_link_db:
+ ut_update_link_db((epon_msg_olt_llid_rec*)data);
+ break;
+
+ case update_port_db:
+ ut_update_port_db((epon_msg_olt_port_rec*)data);
+ break;
+
+ case dump_db:
+ ut_dump_db();
+ break;
+
+ default:
+ break;
+ }
+
+ }
+
+/* Database engine unit test functions */
+static uint16_t epon_db_data_init(void)
+ {
+ uint16_t index;
+ bcmdb_set *db_set;
+ int rc = 0;
+
+ db_set = bcmdb_set_handle(epon_get_db_handle(), epon_olt_link_record);
+ for ( index = 0;
+ (index < MAX_LINKS_PER_HALF_CHIP) && (rc >= 0) && (db_set != NULL) ;
+ index++)
+ {
+ epon_db_olt_llid_rec llid_rec;
+
+ llid_rec.state = unassigned_llid;
+ llid_rec.epon = index/MAX_LINKS_PER_PORT;
+ llid_rec.index = index;
+ rc = bcmdb_record_add(db_set, index, (void *)&llid_rec);
+ }
+
+ db_set = bcmdb_set_handle(epon_get_db_handle(), epon_olt_port_record);
+ for ( index = 0;
+ (index < MAX_PORTS_PER_HALF_CHIP) && (rc >= 0) && (db_set != NULL) ;
+ index++)
+ {
+ epon_db_olt_port_rec port_rec;
+ port_rec.state = disabled;
+ rc = bcmdb_record_add(db_set, index, (void *)&port_rec);
+ }
+ return rc;
+ }
+
+static int epon_db_instance_init(void)
+ {
+ bcmdb_sos_init db_sos_inst;
+ bcmdb_sor_init db_sor_inst;
+ const char* db_name = "EPON STACK";
+ const char* db_llid_name = "EPON LINK REC";
+ const char* db_eport_name = "EPON PORT REC";
+ bcmdb_set *db_sor_set;
+ int rc;
+
+ db_sos_inst.name = db_name;
+ db_sos_inst.backend_type = BCMDB_BACKEND_ARRAY;
+ db_sos_inst.max_entries = num_db_tables;
+ rc = bcmdb_make_set_of_sets(&db_sos_inst, &db_sos_set);
+
+ if (rc >= 0)
+ {
+ db_sor_inst.name = db_llid_name;
+ db_sor_inst.backend_type = BCMDB_BACKEND_ARRAY;
+ db_sor_inst.lock_policy = BCMDB_LOCK_NB_READ_SHADOW_WRITE;
+ db_sor_inst.max_entries = MAX_LINKS_PER_HALF_CHIP;
+ db_sor_inst.record_size = sizeof(epon_db_olt_llid_rec);
+ db_sor_inst.format = NULL;
+ bcmdb_make_set_of_records(&db_sor_inst, BCMOS_TRUE, &db_sor_set);
+
+ rc = bcmdb_set_add(epon_get_db_handle(),
+ epon_olt_link_record, db_sor_set);
+ }
+ if (rc >= 0)
+ {
+ db_sor_inst.name = db_eport_name;
+ db_sor_inst.backend_type = BCMDB_BACKEND_ARRAY;
+ db_sor_inst.lock_policy = BCMDB_LOCK_NB_READ_SHADOW_WRITE;
+ db_sor_inst.max_entries = MAX_PORTS_PER_HALF_CHIP;
+ db_sor_inst.record_size = sizeof(epon_db_olt_port_rec);
+ db_sor_inst.format = NULL;
+ rc = bcmdb_make_set_of_records(&db_sor_inst, BCMOS_TRUE, &db_sor_set);
+ }
+
+ rc = bcmdb_set_add(epon_get_db_handle(), epon_olt_port_record, db_sor_set);
+
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "database creation returnd %d\n", rc);
+
+ if (rc >= 0)
+ {
+ rc = epon_db_data_init();
+ }
+ return rc;
+ }
+
+/* Thread handlers - so that the DB accesses can be tested across multiple
+ threads. */
+static int task1_handler(long data)
+{
+ bcmos_msg_queue *q = (bcmos_msg_queue *)data;
+ bcmos_msg *msg;
+
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "traditional task handler\n");
+
+ while (1)
+ {
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "Waiting for message\n");
+
+ bcmos_msg_recv(q, BCMOS_WAIT_FOREVER, &msg);
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO,
+ "Received message ID %d, data %p\n",
+ msg->type, msg->data);
+
+ ut_msg_handler(msg->type, msg->data);
+ bcmos_usleep(100000);
+ }
+
+ return 0;
+}
+
+
+static bcmos_errno mod1_init(long data)
+{
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "%ld\n", data);
+ return BCM_ERR_OK;
+}
+
+static void mod_msg_handler(bcmos_module_id module_id, bcmos_msg *msg)
+{
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "module %d msg %d data %p\n",
+ module_id, msg->type, msg->data);
+
+ ut_msg_handler(msg->type, msg->data);
+}
+
+
+
+/* Unit test function - */
+int main(int argc, char *argv[])
+{
+ bcmos_task_parm tp = {};
+ bcmos_msg_queue_parm qp = {};
+ bcmos_module_parm mp = {};
+ bcmos_msg msg1 = {};
+ bcmos_msg msg2 = {};
+
+ bcmos_task t1;
+ bcmos_task t2;
+ bcmos_msg_queue q1;
+ bcmos_errno rc;
+ epon_msg_olt_llid_rec link_rec1, link_rec2;
+ epon_msg_olt_port_rec port_msg1, port_msg2;
+
+ bcmos_init();
+ bcmos_trace_level_set(BCMOS_TRACE_LEVEL_DEBUG);
+
+ if (epon_db_instance_init() < 0)
+ {
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_ERROR,
+ "Could not instantiate a Database\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ BCMOS_TRACE(BCMOS_TRACE_LEVEL_INFO, "Database set %p\n",
+ bcmdb_set_handle(db_sos_set, epon_olt_link_record));
+
+ /* Create message queue */
+ qp.name = "msg queue1";
+ qp.size = 16;
+ qp.high_wm = 14;
+ qp.low_wm = 12;
+ rc = bcmos_msg_queue_create(&q1, &qp);
+
+ /* Create a couple of threads */
+ tp.name = "task1";
+ tp.handler = task1_handler;
+ tp.data = (long)&q1;
+ rc = bcmos_task_create(&t1, &tp);
+
+ tp.name = "task2";
+ tp.handler = NULL;
+ tp.data = 0;
+ rc = bcmos_task_create(&t2, &tp);
+
+ /* Register a module */
+ mp.qparm.name = "module1";
+ mp.qparm.size = 16;
+ mp.init = mod1_init;
+ bcmos_module_create(BCMOS_MODULE_ID_TEST1, &t2, &mp);
+
+ /* Wait some */
+ bcmos_usleep(2000000);
+
+ /* Send a message to update the DB - enable a port*/
+ port_msg1.index=5;
+ port_msg1.port_rec.state=enabled;
+ msg1.type = update_port_db;
+ msg1.data = &port_msg1;
+ bcmos_msg_send(&q1, &msg1, BCMOS_MSG_SEND_NO_FREE_ON_ERROR);
+
+ /* Send a message to update the DB - enable a port*/
+ port_msg2.index=3;
+ port_msg2.port_rec.state=enabled;
+ msg2.type = update_port_db;
+ msg2.data = &port_msg2;
+ bcmos_msg_send(&q1, &msg2, BCMOS_MSG_SEND_NO_FREE_ON_ERROR);
+
+ /* Wait some */
+ bcmos_usleep(2000000);
+
+ /* Send a message to update the DB - put a link In Service*/
+ link_rec1.index=14;
+ link_rec1.llid_rec.state=inservice_llid;
+ msg1.type = update_link_db;
+ msg1.data = &link_rec1;
+ bcmos_msg_send(&q1, &msg1, BCMOS_MSG_SEND_NO_FREE_ON_ERROR);
+
+ /* Send a message to update the DB - quarantine a link */
+ link_rec2.index=22;
+ link_rec2.llid_rec.state=quarantined_llid;
+ msg2.type = update_link_db;
+ msg2.data = &link_rec2;
+ msg2.handler = mod_msg_handler;
+ bcmos_msg_send_to_module(BCMOS_MODULE_ID_TEST1, &msg2, BCMOS_MSG_SEND_NO_FREE_ON_ERROR);
+
+ /* Wait some */
+ bcmos_usleep(2000000);
+
+ /* Send a message to dump the DB */
+ msg1.type = dump_db;
+ msg1.handler = mod_msg_handler;
+ msg1.data = NULL;
+ bcmos_msg_send_to_module(BCMOS_MODULE_ID_TEST1, &msg1, BCMOS_MSG_SEND_NO_FREE_ON_ERROR);
+
+
+ /* Wait some */
+ bcmos_usleep(2000000);
+
+ return rc;
+}
diff --git a/bal_release/src/common/debug/ipc_ping/Makefile b/bal_release/src/common/debug/ipc_ping/Makefile
new file mode 100644
index 0000000..07c2b85
--- /dev/null
+++ b/bal_release/src/common/debug/ipc_ping/Makefile
@@ -0,0 +1,36 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# IPC ping debug utility
+#
+MOD_NAME = ipc_ping
+MOD_TYPE = lib
+MOD_DEPS = cli
+srcs = bal_ipc_ping.c
diff --git a/bal_release/src/common/dev_log b/bal_release/src/common/dev_log
new file mode 120000
index 0000000..0c2e71e
--- /dev/null
+++ b/bal_release/src/common/dev_log
@@ -0,0 +1 @@
+../../3rdparty/maple/sdk/host_reference/dev_log
\ No newline at end of file
diff --git a/bal_release/src/common/include/Makefile b/bal_release/src/common/include/Makefile
new file mode 100644
index 0000000..46650aa
--- /dev/null
+++ b/bal_release/src/common/include/Makefile
@@ -0,0 +1,38 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+###############################################################################
+# Common headers
+#
+MOD_NAME = common_include
+MOD_TYPE = lib
+MOD_DEPS =
+gen_bal_hdrs = bal_model_ids.h bal_model_types.h
+
diff --git a/bal_release/src/common/include/bal_buf.h b/bal_release/src/common/include/bal_buf.h
new file mode 100644
index 0000000..c5e06f7
--- /dev/null
+++ b/bal_release/src/common/include/bal_buf.h
@@ -0,0 +1,43 @@
+#ifndef BAL_BUF
+#define BAL_BUF
+
+#include "bcmolt_buf.h"
+
+typedef bcmolt_buf bcmbal_buf;
+
+#define bcmbal_buf_init(buf, size, start) bcmolt_buf_init(buf, size, start, BCMOLT_BUF_ENDIAN_FIXED)
+#define bcmbal_buf_alloc(buf, size) bcmolt_buf_alloc(buf, size, BCMOLT_BUF_ENDIAN_FIXED)
+#define bcmbal_buf_free bcmolt_buf_free
+#define bcmbal_buf_skip bcmolt_buf_skip
+#define bcmbal_buf_set_pos bcmolt_buf_set_pos
+#define bcmbal_buf_get_used bcmolt_buf_get_used
+#define bcmbal_buf_get_remaining_size bcmolt_buf_get_remaining_size
+#define bcmbal_buf_write bcmolt_buf_write
+#define bcmbal_buf_read bcmolt_buf_read
+#define bcmbal_buf_rewind bcmolt_buf_rewind
+#define bcmbal_buf_write_u8 bcmolt_buf_write_u8
+#define bcmbal_buf_read_u8 bcmolt_buf_read_u8
+#define bcmbal_buf_write_u16 bcmolt_buf_write_u16
+#define bcmbal_buf_read_u16 bcmolt_buf_read_u16
+#define bcmbal_buf_write_s16 bcmolt_buf_write_s16
+#define bcmbal_buf_read_s16 bcmolt_buf_read_s16
+#define bcmbal_buf_write_u24 bcmolt_buf_write_u24
+#define bcmbal_buf_read_u24 bcmolt_buf_read_u24
+#define bcmbal_buf_write_u32 bcmolt_buf_write_u32
+#define bcmbal_buf_read_u32 bcmolt_buf_read_u32
+#define bcmbal_buf_write_s32 bcmolt_buf_write_s32
+#define bcmbal_buf_read_s32 bcmolt_buf_read_s32
+#define bcmbal_buf_write_u64 bcmolt_buf_write_u64
+#define bcmbal_buf_read_u64 bcmolt_buf_read_u64
+#define bcmbal_buf_write_bool bcmolt_buf_write_bool
+#define bcmbal_buf_read_bool bcmolt_buf_read_bool
+#define bcmbal_buf_write_mac_address bcmolt_buf_write_mac_address
+#define bcmbal_buf_read_mac_address bcmolt_buf_read_mac_address
+#define bcmbal_buf_write_ipv4_address bcmolt_buf_write_ipv4_address
+#define bcmbal_buf_read_ipv4_address bcmolt_buf_read_ipv4_address
+#define bcmbal_buf_write_ipv6_address bcmolt_buf_write_ipv6_address
+#define bcmbal_buf_read_ipv6_address bcmolt_buf_read_ipv6_address
+#define bcmbal_buf_write_vlan_tag bcmolt_buf_write_vlan_tag
+#define bcmbal_buf_read_vlan_tag bcmolt_buf_read_vlan_tag
+
+#endif /* BAL_BUF */
diff --git a/bal_release/src/common/include/bal_common.h b/bal_release/src/common/include/bal_common.h
new file mode 100644
index 0000000..c5a2558
--- /dev/null
+++ b/bal_release/src/common/include/bal_common.h
@@ -0,0 +1,317 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_common.h
+ *
+ * @brief Common include files and miscellaneous macros for the BAL source code.
+ *
+ */
+
+#ifndef BALCOMMON_H
+#define BALCOMMON_H
+
+/*@{*/
+
+/* --- system includes ---*/
+#include <bcmos_system.h>
+
+/* --- project includes ---*/
+
+/**
+ * @brief OUI Identifier
+ *
+ */
+typedef uint8_t oui_val_t[3];
+
+/*
+ * A max/min function
+ */
+#define max(a,b) ((a > b) ? a : b)
+#define min(a,b) ((a > b) ? b : a)
+
+/**
+ * @brief Maximum value for a VLAN ID
+ */
+#define MAX_VLAN_ID 4094
+
+/**
+ * @brief Minimum value for an 802.1ah I-SID
+ *
+ * Notes from IEEE:
+ * 0 - Reserved for use by future amendments to the standard.
+ * 1 - Default value, unassigned ISID.
+ * 2..FF - Reserved for use by future amendments to the standard.
+ */
+#define MIN_8021AH_ISID 0x00000100
+
+/**
+ * @brief Maximum value for an 802.1ah I-SID
+ *
+ * Notes from IEEE:
+ * FFFFFF is reserved by IEEE
+ */
+#define MAX_8021AH_ISID 0x00FFFFFE
+
+/**
+ * @brief VLAN TPID definitions
+ */
+typedef enum vlan_tpid_type
+{
+ VLAN_TPID_TYPE_DEFAULT = 0x0000, /**< Simple Bridge - i.e. VID 0, no tagging */
+ VLAN_TPID_TYPE_8021Q = 0x8100, /**< C-VLAN */
+ VLAN_TPID_TYPE_8021AD = 0x88A8, /**< S-VLAN */
+ VLAN_TPID_TYPE_9100 = 0x9100, /**< Legacy TPID */
+ VLAN_TPID_TYPE_9200 = 0x9200, /**< Legacy TPID */
+ VLAN_TPID_TYPE_9300 = 0x9300, /**< Legacy TPID */
+ VLAN_TPID_TYPE_8021AH_ITAG = 0x88E7 /**< 802.1ah I-Tag TPID */
+} vlan_tpid_type;
+
+/**
+ * @brief VLAN type definitions
+ */
+typedef enum vlan_mode_type
+{
+ VLAN_MODE_NONE, /**< Neither Shared or L2VPN */
+ VLAN_MODE_SHARED, /**< IP-based shared vlan */
+ VLAN_MODE_8021AD_EN, /**< DPoE 802.1ad (or .1q) encapsulation mode */
+ VLAN_MODE_8021AD_TP, /**< DPoE 802.1ad (or .1q) transport mode */
+ VLAN_MODE_8021AH_EN, /**< DPoE 802.1ah encapsulation mode */
+ VLAN_MODE_8021AH_TP, /**< DPoE 802.1ah transport mode */
+ VLAN_MODE_DAC /**< DPoE DEMARC Auto Configuration */
+} vlan_mode;
+
+/**
+ * @brief Macro to test if a VLAN is 802.1ad
+ */
+#define VLAN_IS_8021AD(_vlan_) (((_vlan_)->type == VLAN_MODE_8021AD_EN) || ((_vlan_)->type == VLAN_MODE_8021AD_TP))
+
+/**
+ * @brief Macro to test if a VLAN is 802.1ah
+ */
+#define VLAN_IS_8021AH(_vlan_) (((_vlan_)->type == VLAN_MODE_8021AH_EN) || ((_vlan_)->type == VLAN_MODE_8021AH_TP))
+
+/**
+ * @brief Macro to test if a VLAN is L2VPN (as opposed to 'None' or "Shared')
+ */
+#define VLAN_IS_L2VPN(_vlan_) (VLAN_IS_8021AD(_vlan_) || VLAN_IS_8021AH(_vlan_))
+
+/**
+ * @brief Macro to test if a VLAN is DPoE IP-HSD
+ */
+#define VLAN_IS_DPOE_IPHSD(_vlan_) (((_vlan_)->type == VlanType_None) && ((_vlan_)->dpoeIp.svid != 0) && ((_vlan_)->dpoeIp.cvid != 0))
+
+/**
+ * @brief Macro to test if a VLAN is Legacy IP-HSD
+ */
+#define VLAN_IS_LEGACY_IPHSD(_vlan_) (((_vlan_)->type == VlanType_None) && ((_vlan_)->dpoeIp.svid == 0))
+
+/**
+ * @brief Macro to test if a VLAN is DPoE IP-HSD with PON-NNI style tagging
+ */
+#define VLAN_IS_DPOE_IPHSD_PON_NNI(_vlan_) (VLAN_IS_DPOE_IPHSD(_vlan_) && ((_vlan_)->dot1ad[VLAN_TAG_OUTER].nniTpid != 0))
+
+/**
+ * @brief Macro to test if a VLAN is Shared
+ */
+#define VLAN_IS_SHARED(_vlan_) ((_vlan_)->type == VLAN_MODE_SHARED)
+
+/**
+ * @brief 802.1ad VLAN Tag index
+ *
+ * This enum is used in the VlanT structure to address the outer vs. the inner
+ * 802.1ad tag.
+ */
+typedef enum vlan_tag_index
+{
+ VLAN_TAG_INDEX_OUTER = 0, /**< Outer tag, typically the S-VLAN tag */
+ VLAN_TAG_INDEX_INNER = 1, /**< Inner tag, typically the C-VLAN tag */
+ VLAN_TAG_INDEX_MAX = 2
+} vlan_tag_index;
+
+/**
+ * @brief VlanT structure
+ */
+typedef struct bcmbal_vlan
+{
+ vlan_mode type; /**< Type of VLAN */
+
+ /** Intra-Chassis Tagging */
+ struct
+ {
+ uint16_t tpid; /**< ICT TPID */
+ uint16_t vid; /**< ICT VLAN ID */
+ } ict;
+
+ /** DPoE IP HSD Tagging */
+ struct
+ {
+ uint16_t svid; /**< S-TAG VID */
+ uint16_t cvid; /**< C-TAG VID */
+ } dpoe_ip;
+
+ /** 802.1ad (and 802.1q) tagging */
+ struct
+ {
+ uint16_t nni_tpid; /**< VLAN Tag TPID used on the NNI */
+ uint16_t uni_tpid; /**< VLAN Tag TPID used on the UNI */
+ uint8_t cos; /**< CoS bits used in this VLAN Tag */
+ uint16_t vid; /**< VLAN ID */
+ } dot_1ad[VLAN_TAG_INDEX_MAX];
+
+ /** 802.1ah encapsulation info */
+ struct
+ {
+ /** 802.1ah B-MACs */
+ bcmos_mac_address bda; /**< 802.1ah Destination B-MAC */
+ bcmos_mac_address bsa; /**< 802.1ah Source B-MAC */
+
+ /** 802.1ah B-Tag */
+ struct
+ {
+ uint16_t nni_tpid; /**< B-Tag TPID used on the NNI */
+ uint16_t uni_tpid; /**< B-Tag TPID used on the UNI */
+ uint16_t vid; /**< B-Tag VLAN ID */
+ } btag;
+
+ /** 802.1ah I-Tag */
+ struct
+ {
+ uint16_t nni_tpid; /**< I-Tag TPID used on the NNI */
+ uint16_t uni_tpid; /**< I-Tag TPID used on the UNI */
+ uint32_t isid; /**< I-Tag Service ID */
+ } itag;
+ } dot_1ah;
+
+ /** L2VPN specific VLAN configuration */
+ uint32_t vpn_idx; /**< Index of L2VPN that link is associated with. */
+} bcmbal_vlan;
+
+/**
+ * @brief MAC Address key structure.
+ *
+ * This structure effectively adds a length field to the MacAddressT structure
+ * which helps when handling GetNext requests that don't contain a full MAC
+ * Address.
+ */
+typedef struct mac_address_key
+{
+ bcmos_mac_address mac_addr; /**< The MAC address */
+ uint16_t len; /**< The length of the MAC address in the field above */
+} mac_address_key;
+
+/**
+ * @brief MAC Address length
+ */
+#define MAC_ADDRESS_LEN 6
+
+/**
+ * @brief Converts a MacAddressT structure into a MacAddressKeyT structure.
+ */
+#define MAC_ADDR_TO_KEY(A, K, L) { \
+ (K)->mac_addr = *(A); \
+ (K)->len = (L); \
+ }
+
+/**
+ * @brief Compares the 802.1ad (or q) fields of two VlanT objects
+ *
+ * This macro returns '1' if all fields match, and '0' otherwise.
+ *
+ * Note, this macro looks at the nniTpid only. This macro is used to determine
+ * whether or not an OLT Domain already exists for a given VLAN (which prevents
+ * configuring duplicate/overlapping OLT domain selectors).
+ *
+ */
+#define VLANS_MATCH_AD(_vlan1_, _vlan2_) (((_vlan1_)->dot1ad[VLAN_TAG_OUTER].vid == (_vlan2_)->dot1ad[VLAN_TAG_OUTER].vid) && \
+ ((_vlan1_)->dot1ad[VLAN_TAG_OUTER].nniTpid == (_vlan2_)->dot1ad[VLAN_TAG_OUTER].nniTpid) && \
+ ((_vlan1_)->dot1ad[VLAN_TAG_INNER].vid == (_vlan2_)->dot1ad[VLAN_TAG_INNER].vid) && \
+ ((_vlan1_)->dot1ad[VLAN_TAG_INNER].nniTpid == (_vlan2_)->dot1ad[VLAN_TAG_INNER].nniTpid))
+
+/**
+ * @brief Compares the 802.1ah (mac-in-mac) fields of two VlanT objects
+ *
+ * This macro returns '1' if all fields match, and '0' otherwise.
+ *
+ * Note, this macro looks at the nniTpid's only. This macro is used to
+ * determine whether or not an OLT Domain already exists for a given VLAN
+ * (which prevents configuring duplicate/overlapping OLT domain selectors).
+ *
+ */
+#define VLANS_MATCH_AH(_vlan1_, _vlan2_) (((_vlan1_)->dot1ah.btag.nniTpid == (_vlan2_)->dot1ah.btag.nniTpid) && \
+ ((_vlan1_)->dot1ah.btag.vid == (_vlan2_)->dot1ah.btag.vid) && \
+ ((_vlan1_)->dot1ah.itag.nniTpid == (_vlan2_)->dot1ah.itag.nniTpid) && \
+ ((_vlan1_)->dot1ah.itag.isid == (_vlan2_)->dot1ah.itag.isid))
+
+/**
+ * @brief Compares the ICT fields of two VlanT objects
+ *
+ * This macro returns '1' if all fields match, and '0' otherwise.
+ *
+ * Note, this macro looks at the ICT fields only. This macro is
+ * used to determine whether or not an OLT Domain already
+ * exists for a given VLAN (which prevents configuring
+ * duplicate/overlapping OLT domain selectors).
+ *
+ */
+#define VLANS_MATCH_ICT(_vlan1_, _vlan2_) (((_vlan1_)->ict.tpid == (_vlan2_)->ict.tpid) && \
+ ((_vlan1_)->ict.vid == (_vlan2_)->ict.vid))
+/**
+ * @brief Compares the 802.1ad (or q) and 802.1ah (mac-in-mac)
+ * fields of two VlanT objects
+ *
+ * This macro returns '1' if all fields match, and '0' otherwise.
+ *
+ */
+#define VLANS_MATCH(_vlan1_, _vlan2_) (VLANS_MATCH_AD(_vlan1_, _vlan2_) && VLANS_MATCH_AH(_vlan1_, _vlan2_))
+
+/**
+ * @brief Macros for setting/clearing bits inside of an integer
+ */
+#define SET_BIT(x,n) ((x) |= (1L << (n)))
+#define CLR_BIT(x,n) ((x) &= (~(1L << (n))))
+#define BIT_IS_SET(x,n) (((x) >> (n)) & 1)
+
+
+
+/**
+ * Static compile time assert used to ensure that enums and associated
+ * character arrays are equal.
+ *
+ * Use the BAL_STATIC_ASSERT function in your code to check array sizes
+ */
+#define _BAL_STATIC_ASSERT_HELPER(expr, msg) (sizeof (struct {unsigned int STATIC_ASSERT__##msg: (expr) ? 1 : -1;} ))
+
+#define BAL_STATIC_ASSERT(expr, msg) extern int (*assert_function__##msg(void)) [_BAL_STATIC_ASSERT_HELPER(expr, msg) ]
+
+/*@}*/
+
+#endif /* #ifndef BALCOMMON_H */
diff --git a/bal_release/src/common/include/bal_ids.h b/bal_release/src/common/include/bal_ids.h
new file mode 100644
index 0000000..e4239e6
--- /dev/null
+++ b/bal_release/src/common/include/bal_ids.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_ids.h
+ * @brief BAL IDs used in the system
+ *
+ * This file contains all of the BAL IDs used in the system
+ *
+ */
+#ifndef BALIDS_H
+#define BALIDS_H
+
+/*@{*/
+
+/*@}*/
+
+#endif /* #ifndef BALIDS_H */
diff --git a/bal_release/src/common/include/bal_model_ids.h b/bal_release/src/common/include/bal_model_ids.h
new file mode 100644
index 0000000..218b74e
--- /dev/null
+++ b/bal_release/src/common/include/bal_model_ids.h
@@ -0,0 +1,714 @@
+#ifndef BAL_MODEL_IDS_H_
+#define BAL_MODEL_IDS_H_
+
+/** \ingroup object_model_data_types
+ * \defgroup object_model_enums BAL Object Model Enumerations
+ */
+
+/** \addtogroup object_model_enums
+ * @{
+ */
+#include <bcmos_system.h>
+
+/** Identifiers for all properties contained in the access_terminal_cfg group.
+ */
+typedef enum bcmbal_access_terminal_cfg_id
+{
+ BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE = 2, /**< Interworking function mode. */
+ BCMBAL_ACCESS_TERMINAL_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_access_terminal_cfg_id;
+
+/** Identifiers for all properties contained in the access_terminal_ind group.
+ */
+typedef enum bcmbal_access_terminal_ind_id
+{
+ BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE = 2, /**< Interworking function mode. */
+ BCMBAL_ACCESS_TERMINAL_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_access_terminal_ind_id;
+
+/** Identifiers for all properties contained in the access_terminal_key group.
+ */
+typedef enum bcmbal_access_terminal_key_id
+{
+ BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID= 0, /**< access_term_id. */
+ BCMBAL_ACCESS_TERMINAL_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_access_terminal_key_id;
+
+/** Identifiers for all properties contained in the flow_cfg group.
+ */
+typedef enum bcmbal_flow_cfg_id
+{
+ BCMBAL_FLOW_CFG_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_FLOW_CFG_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID = 2, /**< Access Interface ID. */
+ BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID = 3, /**< Network Interface ID. */
+ BCMBAL_FLOW_CFG_ID_SUB_TERM_ID = 4, /**< Subscriber Terminal ID. */
+ BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX = 5, /**< Subscriber Terminal uni port index. */
+ BCMBAL_FLOW_CFG_ID_SVC_PORT_ID = 6, /**< Service Port ID. */
+ BCMBAL_FLOW_CFG_ID_AGG_PORT_ID = 7, /**< Aggregate port ID. */
+ BCMBAL_FLOW_CFG_ID_RESOLVE_MAC = 8, /**< Resolve mac. */
+ BCMBAL_FLOW_CFG_ID_CLASSIFIER = 9, /**< Classifier. */
+ BCMBAL_FLOW_CFG_ID_ACTION = 10, /**< Action. */
+ BCMBAL_FLOW_CFG_ID_SLA = 11, /**< SLA. */
+ BCMBAL_FLOW_CFG_ID_COOKIE = 12, /**< Cookie. */
+ BCMBAL_FLOW_CFG_ID_PRIORITY = 13, /**< Priority. */
+ BCMBAL_FLOW_CFG_ID_GROUP_ID = 14, /**< Group ID. */
+ BCMBAL_FLOW_CFG_ID_QUEUE = 15, /**< Egress queue. */
+ BCMBAL_FLOW_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_flow_cfg_id;
+
+/** Identifiers for all properties contained in the flow_ind group.
+ */
+typedef enum bcmbal_flow_ind_id
+{
+ BCMBAL_FLOW_IND_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_FLOW_IND_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_FLOW_IND_ID_ACCESS_INT_ID = 2, /**< Access interface ID. */
+ BCMBAL_FLOW_IND_ID_NETWORK_INT_ID = 3, /**< Network Interface ID. */
+ BCMBAL_FLOW_IND_ID_SUB_TERM_ID = 4, /**< Subscriber terminal ID. */
+ BCMBAL_FLOW_IND_ID_SVC_PORT_ID = 5, /**< Service port ID. */
+ BCMBAL_FLOW_IND_ID_AGG_PORT_ID = 6, /**< Aggregate port ID. */
+ BCMBAL_FLOW_IND_ID_RESOLVE_MAC = 7, /**< Resolve mac. */
+ BCMBAL_FLOW_IND_ID_BASE_TC_ID = 8, /**< Base TCONT ID. */
+ BCMBAL_FLOW_IND_ID_CLASSIFIER = 9, /**< Classifier. */
+ BCMBAL_FLOW_IND_ID_ACTION = 10, /**< Action. */
+ BCMBAL_FLOW_IND_ID_SLA = 11, /**< SLA. */
+ BCMBAL_FLOW_IND_ID_COOKIE = 12, /**< Cookie. */
+ BCMBAL_FLOW_IND_ID_PRIORITY = 13, /**< Priority. */
+ BCMBAL_FLOW_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_flow_ind_id;
+
+/** Identifiers for all properties contained in the flow_key group.
+ */
+typedef enum bcmbal_flow_key_id
+{
+ BCMBAL_FLOW_KEY_ID_FLOW_ID = 0, /**< Flow ID. */
+ BCMBAL_FLOW_KEY_ID_FLOW_TYPE = 1, /**< Flow type. */
+ BCMBAL_FLOW_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_flow_key_id;
+
+/** Identifiers for all properties contained in the flow_stat group.
+ */
+typedef enum bcmbal_flow_stat_id
+{
+ BCMBAL_FLOW_STAT_ID_RX_PACKETS = 0, /**< Received packets. */
+ BCMBAL_FLOW_STAT_ID_RX_BYTES = 1, /**< Received bytes. */
+ BCMBAL_FLOW_STAT_ID_TX_PACKETS = 2, /**< Transmitted packets. */
+ BCMBAL_FLOW_STAT_ID_TX_BYTES = 3, /**< Transmitted bytes. */
+ BCMBAL_FLOW_STAT_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_flow_stat_id;
+
+/** Identifiers for all properties contained in the group_cfg group.
+ */
+typedef enum bcmbal_group_cfg_id
+{
+ BCMBAL_GROUP_CFG_ID_MEMBERS_CMD = 0, /**< Membership operation commands. */
+ BCMBAL_GROUP_CFG_ID_MEMBERS = 1, /**< Member. */
+ BCMBAL_GROUP_CFG_ID_COOKIE = 2, /**< Application cookie. */
+ BCMBAL_GROUP_CFG_ID_FLOWS = 3, /**< List of flows associated with the group . */
+ BCMBAL_GROUP_CFG_ID_OWNER = 4, /**< Owner of the group. */
+ BCMBAL_GROUP_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_group_cfg_id;
+
+/** Identifiers for all properties contained in the group_key group.
+ */
+typedef enum bcmbal_group_key_id
+{
+ BCMBAL_GROUP_KEY_ID_GROUP_ID = 0, /**< Group ID. */
+ BCMBAL_GROUP_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_group_key_id;
+
+/** Identifiers for all properties contained in the interface_cfg group.
+ */
+typedef enum bcmbal_interface_cfg_id
+{
+ BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_INTERFACE_CFG_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID= 2, /**< Minimum aggregate port ID. */
+ BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID= 3, /**< Minimum service port ID. */
+ BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE = 4, /**< Transceiver type. */
+ BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE = 5, /**< Downstream unknown packet action. */
+ BCMBAL_INTERFACE_CFG_ID_MTU = 6, /**< MTU. */
+ BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL = 7, /**< Flow control. */
+ BCMBAL_INTERFACE_CFG_ID_DS_TM = 8, /**< Downstream scheduler and shaper. */
+ BCMBAL_INTERFACE_CFG_ID_US_TM = 9, /**< Upstream scheduler and shaper. */
+ BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST = 10, /**< Sub-term id list. */
+ BCMBAL_INTERFACE_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_interface_cfg_id;
+
+/** Identifiers for all properties contained in the interface_ind group.
+ */
+typedef enum bcmbal_interface_ind_id
+{
+ BCMBAL_INTERFACE_IND_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_INTERFACE_IND_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID= 2, /**< Minimum aggregate port ID. */
+ BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID= 3, /**< Minimum service port ID. */
+ BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE = 4, /**< Transceiver type. */
+ BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE = 5, /**< Downstream unknown packet action. */
+ BCMBAL_INTERFACE_IND_ID_MTU = 6, /**< MTU. */
+ BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL = 7, /**< Flow control. */
+ BCMBAL_INTERFACE_IND_ID_DS_TM = 8, /**< Downstream scheduler and shaper. */
+ BCMBAL_INTERFACE_IND_ID_US_TM = 9, /**< Upstream scheduler and shaper. */
+ BCMBAL_INTERFACE_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_interface_ind_id;
+
+/** Identifiers for all properties contained in the interface_key group.
+ */
+typedef enum bcmbal_interface_key_id
+{
+ BCMBAL_INTERFACE_KEY_ID_INTF_ID = 0, /**< intf_id. */
+ BCMBAL_INTERFACE_KEY_ID_INTF_TYPE = 1, /**< intf_type. */
+ BCMBAL_INTERFACE_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_interface_key_id;
+
+/** Identifiers for all properties contained in the interface_stat group.
+ */
+typedef enum bcmbal_interface_stat_id
+{
+ BCMBAL_INTERFACE_STAT_ID_RX_PACKETS = 0, /**< Recieved packets. */
+ BCMBAL_INTERFACE_STAT_ID_RX_BYTES = 1, /**< Received bytes. */
+ BCMBAL_INTERFACE_STAT_ID_TX_PACKETS = 2, /**< Transmitted packets. */
+ BCMBAL_INTERFACE_STAT_ID_TX_BYTES = 3, /**< Transmitted bytes. */
+ BCMBAL_INTERFACE_STAT_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_interface_stat_id;
+
+/** Identifiers for all properties contained in the packet_cfg group.
+ */
+typedef enum bcmbal_packet_cfg_id
+{
+ BCMBAL_PACKET_CFG_ID_FLOW_ID = 0, /**< Flow Id. */
+ BCMBAL_PACKET_CFG_ID_FLOW_TYPE = 1, /**< Flow Type. */
+ BCMBAL_PACKET_CFG_ID_INTF_ID = 2, /**< Interface ID. */
+ BCMBAL_PACKET_CFG_ID_INTF_TYPE = 3, /**< Interface Type. */
+ BCMBAL_PACKET_CFG_ID_SVC_PORT = 4, /**< Service Port. */
+ BCMBAL_PACKET_CFG_ID_FLOW_COOKIE = 5, /**< Flow Cookie. */
+ BCMBAL_PACKET_CFG_ID_PKT = 6, /**< Packet Data. */
+ BCMBAL_PACKET_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_packet_cfg_id;
+
+/** Identifiers for all properties contained in the packet_ind group.
+ */
+typedef enum bcmbal_packet_ind_id
+{
+ BCMBAL_PACKET_IND_ID_FLOW_ID = 0, /**< Flow Id. */
+ BCMBAL_PACKET_IND_ID_FLOW_TYPE = 1, /**< Flow Type. */
+ BCMBAL_PACKET_IND_ID_INTF_ID = 2, /**< Interface ID. */
+ BCMBAL_PACKET_IND_ID_INTF_TYPE = 3, /**< Interface Type. */
+ BCMBAL_PACKET_IND_ID_SVC_PORT = 4, /**< Service Port. */
+ BCMBAL_PACKET_IND_ID_FLOW_COOKIE = 5, /**< Flow Cookie. */
+ BCMBAL_PACKET_IND_ID_PKT = 6, /**< Packet Data. */
+ BCMBAL_PACKET_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_packet_ind_id;
+
+/** Identifiers for all properties contained in the packet_key group.
+ */
+typedef enum bcmbal_packet_key_id
+{
+ BCMBAL_PACKET_KEY_ID_RESERVED = 0, /**< Reserved key field. */
+ BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST = 1, /**< Packet destination. */
+ BCMBAL_PACKET_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_packet_key_id;
+
+/** Identifiers for all properties contained in the subscriber_terminal_cfg
+ * group.
+ */
+typedef enum bcmbal_subscriber_terminal_cfg_id
+{
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER = 2, /**< Serial number. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD = 3, /**< Password. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID = 4, /**< Registration id. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID = 5, /**< Service port ID. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS = 6, /**< MAC address. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM = 7, /**< Downstream scheduler and shaper. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM = 8, /**< Upstream scheduler and shaper. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST = 9, /**< svc_port_id list. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST = 10, /**< agg_port_id list. */
+ BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_subscriber_terminal_cfg_id;
+
+/** Identifiers for all properties contained in the subscriber_terminal_ind
+ * group.
+ */
+typedef enum bcmbal_subscriber_terminal_ind_id
+{
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE = 0, /**< Administrative state. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS = 1, /**< Operational status. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER = 2, /**< Serial number. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD = 3, /**< Password. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID = 4, /**< Registration id. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID = 5, /**< Service port ID. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS = 6, /**< MAC address. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM = 7, /**< Downstream scheduler and shaper. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM = 8, /**< Upstream scheduler and shaper. */
+ BCMBAL_SUBSCRIBER_TERMINAL_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_subscriber_terminal_ind_id;
+
+/** Identifiers for all properties contained in the subscriber_terminal_key
+ * group.
+ */
+typedef enum bcmbal_subscriber_terminal_key_id
+{
+ BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID = 0, /**< sub_term_id. */
+ BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID = 1, /**< intf_id. */
+ BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_subscriber_terminal_key_id;
+
+/** Identifiers for all properties contained in the subscriber_terminal_stat
+ * group.
+ */
+typedef enum bcmbal_subscriber_terminal_stat_id
+{
+ BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS = 0, /**< Received packets. */
+ BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES = 1, /**< Received bytes. */
+ BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS = 2, /**< Transmitted packets. */
+ BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES = 3, /**< Transmitted bytes. */
+ BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_subscriber_terminal_stat_id;
+
+/** Identifiers for all properties contained in the tm_queue_cfg group.
+ */
+typedef enum bcmbal_tm_queue_cfg_id
+{
+ BCMBAL_TM_QUEUE_CFG_ID_PRIORITY = 0, /**< priority. */
+ BCMBAL_TM_QUEUE_CFG_ID_WEIGHT = 1, /**< weight. */
+ BCMBAL_TM_QUEUE_CFG_ID_RATE = 2, /**< rate. */
+ BCMBAL_TM_QUEUE_CFG_ID_BAC = 3, /**< bac. */
+ BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE = 4, /**< creation_mode. */
+ BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT = 5, /**< ref_count. */
+ BCMBAL_TM_QUEUE_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_queue_cfg_id;
+
+/** Identifiers for all properties contained in the tm_queue_ind group.
+ */
+typedef enum bcmbal_tm_queue_ind_id
+{
+ BCMBAL_TM_QUEUE_IND_ID_RET = 0, /**< ret. */
+ BCMBAL_TM_QUEUE_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_queue_ind_id;
+
+/** Identifiers for all properties contained in the tm_queue_key group.
+ */
+typedef enum bcmbal_tm_queue_key_id
+{
+ BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID = 0, /**< sched_id. */
+ BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR = 1, /**< sched dir. */
+ BCMBAL_TM_QUEUE_KEY_ID_ID = 2, /**< id. */
+ BCMBAL_TM_QUEUE_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_queue_key_id;
+
+/** Identifiers for all properties contained in the tm_queue_stat group.
+ */
+typedef enum bcmbal_tm_queue_stat_id
+{
+ BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK = 0, /**< packets_ok. */
+ BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK = 1, /**< bytes_ok. */
+ BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED = 2, /**< packets_discarded. */
+ BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED = 3, /**< bytes_discarded. */
+ BCMBAL_TM_QUEUE_STAT_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_queue_stat_id;
+
+/** Identifiers for all properties contained in the tm_sched_cfg group.
+ */
+typedef enum bcmbal_tm_sched_cfg_id
+{
+ BCMBAL_TM_SCHED_CFG_ID_OWNER = 0, /**< owner. */
+ BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE = 1, /**< type. */
+ BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT = 2, /**< parent. */
+ BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE = 3, /**< child_type. */
+ BCMBAL_TM_SCHED_CFG_ID_RATE = 4, /**< rate. */
+ BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA = 5, /**< tcont_sla. */
+ BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE = 6, /**< creation_mode. */
+ BCMBAL_TM_SCHED_CFG_ID_QUEUES = 7, /**< queues. */
+ BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS = 8, /**< sub_scheds. */
+ BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES = 9, /**< num_priorities. */
+ BCMBAL_TM_SCHED_CFG_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_cfg_id;
+
+/** Identifiers for all properties contained in the tm_sched_ind group.
+ */
+typedef enum bcmbal_tm_sched_ind_id
+{
+ BCMBAL_TM_SCHED_IND_ID_RET = 0, /**< ret. */
+ BCMBAL_TM_SCHED_IND_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_ind_id;
+
+/** Identifiers for all properties contained in the tm_sched_key group.
+ */
+typedef enum bcmbal_tm_sched_key_id
+{
+ BCMBAL_TM_SCHED_KEY_ID_DIR = 0, /**< dir. */
+ BCMBAL_TM_SCHED_KEY_ID_ID = 1, /**< id. */
+ BCMBAL_TM_SCHED_KEY_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_key_id;
+
+/** All object tags for all objects in the system.
+ */
+typedef enum bcmbal_obj_tag
+{
+ BCMBAL_OBJ_TAG__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_obj_tag;
+
+/** Identifiers for all objects in the system.
+ */
+typedef enum bcmbal_obj_id
+{
+ BCMBAL_OBJ_ID__BEGIN,
+ BCMBAL_OBJ_ID_ACCESS_TERMINAL = 0, /**< BAL Access Terminal */
+ BCMBAL_OBJ_ID_FLOW = 1, /**< BAL Flow */
+ BCMBAL_OBJ_ID_GROUP = 2, /**< BAL Group */
+ BCMBAL_OBJ_ID_INTERFACE = 3, /**< BAL Interface */
+ BCMBAL_OBJ_ID_PACKET = 4, /**< packet */
+ BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL = 5, /**< BAL Subscriber Terminal */
+ BCMBAL_OBJ_ID_TM_QUEUE = 6, /**< tm_queue */
+ BCMBAL_OBJ_ID_TM_SCHED = 7, /**< tm_sched */
+ BCMBAL_OBJ_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_obj_id;
+
+/** Identifiers for all possible groups under all objects in the system.
+ */
+typedef enum bcmbal_obj_group_id
+{
+ BCMBAL_OBJ_GROUP_ID__BEGIN,
+ BCMBAL_OBJ_GROUP_ID_ACCESS_TERMINAL_KEY = 0, /**< BAL Access Terminal - key */
+ BCMBAL_OBJ_GROUP_ID_ACCESS_TERMINAL_CFG = 1, /**< BAL Access Terminal - cfg */
+ BCMBAL_OBJ_GROUP_ID_ACCESS_TERMINAL_IND = 2, /**< BAL Access Terminal - Access Terminal Indication */
+ BCMBAL_OBJ_GROUP_ID_FLOW_KEY = 3, /**< BAL Flow - key */
+ BCMBAL_OBJ_GROUP_ID_FLOW_CFG = 4, /**< BAL Flow - cfg */
+ BCMBAL_OBJ_GROUP_ID_FLOW_STAT = 5, /**< BAL Flow - stat */
+ BCMBAL_OBJ_GROUP_ID_FLOW_IND = 6, /**< BAL Flow - Flow Indication */
+ BCMBAL_OBJ_GROUP_ID_GROUP_KEY = 7, /**< BAL Group - key */
+ BCMBAL_OBJ_GROUP_ID_GROUP_CFG = 8, /**< BAL Group - cfg */
+ BCMBAL_OBJ_GROUP_ID_INTERFACE_KEY = 9, /**< BAL Interface - key */
+ BCMBAL_OBJ_GROUP_ID_INTERFACE_CFG = 10, /**< BAL Interface - cfg */
+ BCMBAL_OBJ_GROUP_ID_INTERFACE_STAT = 11, /**< BAL Interface - stat */
+ BCMBAL_OBJ_GROUP_ID_INTERFACE_IND = 12, /**< BAL Interface - Interface Indication */
+ BCMBAL_OBJ_GROUP_ID_PACKET_KEY = 13, /**< packet - key */
+ BCMBAL_OBJ_GROUP_ID_PACKET_CFG = 14, /**< packet - cfg */
+ BCMBAL_OBJ_GROUP_ID_PACKET_IND = 15, /**< packet - Packet indication */
+ BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_KEY = 16, /**< BAL Subscriber Terminal - key */
+ BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_CFG = 17, /**< BAL Subscriber Terminal - cfg */
+ BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_STAT = 18, /**< BAL Subscriber Terminal - stat */
+ BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_IND = 19, /**< BAL Subscriber Terminal - Subscriber Terminal Indication */
+ BCMBAL_OBJ_GROUP_ID_TM_QUEUE_KEY = 20, /**< tm_queue - key */
+ BCMBAL_OBJ_GROUP_ID_TM_QUEUE_CFG = 21, /**< tm_queue - cfg */
+ BCMBAL_OBJ_GROUP_ID_TM_QUEUE_STAT = 22, /**< tm_queue - stat */
+ BCMBAL_OBJ_GROUP_ID_TM_QUEUE_IND = 23, /**< tm_queue - Tm Queue Indication */
+ BCMBAL_OBJ_GROUP_ID_TM_SCHED_KEY = 24, /**< tm_sched - key */
+ BCMBAL_OBJ_GROUP_ID_TM_SCHED_CFG = 25, /**< tm_sched - cfg */
+ BCMBAL_OBJ_GROUP_ID_TM_SCHED_IND = 26, /**< tm_sched - Tm Sched Indication */
+ BCMBAL_OBJ_GROUP_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_obj_group_id;
+
+/** List of all access_terminal groups of type auto.
+ */
+typedef enum bcmbal_access_terminal_auto_id
+{
+ BCMBAL_ACCESS_TERMINAL_AUTO_ID__BEGIN,
+ BCMBAL_ACCESS_TERMINAL_AUTO_ID_IND = 0, /**< Access Terminal Indication. */
+ BCMBAL_ACCESS_TERMINAL_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_access_terminal_auto_id;
+
+/** List of all flow groups of type auto.
+ */
+typedef enum bcmbal_flow_auto_id
+{
+ BCMBAL_FLOW_AUTO_ID__BEGIN,
+ BCMBAL_FLOW_AUTO_ID_IND = 0, /**< Flow Indication. */
+ BCMBAL_FLOW_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_flow_auto_id;
+
+/** List of all interface groups of type auto.
+ */
+typedef enum bcmbal_interface_auto_id
+{
+ BCMBAL_INTERFACE_AUTO_ID__BEGIN,
+ BCMBAL_INTERFACE_AUTO_ID_IND = 0, /**< Interface Indication. */
+ BCMBAL_INTERFACE_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_interface_auto_id;
+
+/** List of all packet groups of type auto.
+ */
+typedef enum bcmbal_packet_auto_id
+{
+ BCMBAL_PACKET_AUTO_ID__BEGIN,
+ BCMBAL_PACKET_AUTO_ID_IND = 0, /**< Packet indication. */
+ BCMBAL_PACKET_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_packet_auto_id;
+
+/** List of all subscriber_terminal groups of type auto.
+ */
+typedef enum bcmbal_subscriber_terminal_auto_id
+{
+ BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID__BEGIN,
+ BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID_IND = 0, /**< Subscriber Terminal Indication. */
+ BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_subscriber_terminal_auto_id;
+
+/** List of all tm_queue groups of type auto.
+ */
+typedef enum bcmbal_tm_queue_auto_id
+{
+ BCMBAL_TM_QUEUE_AUTO_ID__BEGIN,
+ BCMBAL_TM_QUEUE_AUTO_ID_IND = 0, /**< Tm Queue Indication. */
+ BCMBAL_TM_QUEUE_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_queue_auto_id;
+
+/** List of all tm_sched groups of type auto.
+ */
+typedef enum bcmbal_tm_sched_auto_id
+{
+ BCMBAL_TM_SCHED_AUTO_ID__BEGIN,
+ BCMBAL_TM_SCHED_AUTO_ID_IND = 0, /**< Tm Sched Indication. */
+ BCMBAL_TM_SCHED_AUTO_ID__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_auto_id;
+
+#define bcmbal_access_terminal_key_id_all_properties BCMBAL_ACCESS_TERMINAL_KEY_ID__NUM_OF
+#define bcmbal_access_terminal_cfg_id_all_properties BCMBAL_ACCESS_TERMINAL_CFG_ID__NUM_OF
+#define bcmbal_access_terminal_ind_id_all_properties BCMBAL_ACCESS_TERMINAL_IND_ID__NUM_OF
+#define bcmbal_flow_cfg_id_all_properties BCMBAL_FLOW_CFG_ID__NUM_OF
+#define bcmbal_flow_key_id_all_properties BCMBAL_FLOW_KEY_ID__NUM_OF
+#define bcmbal_flow_stat_id_all_properties BCMBAL_FLOW_STAT_ID__NUM_OF
+#define bcmbal_flow_ind_id_all_properties BCMBAL_FLOW_IND_ID__NUM_OF
+#define bcmbal_group_cfg_id_all_properties BCMBAL_GROUP_CFG_ID__NUM_OF
+#define bcmbal_group_key_id_all_properties BCMBAL_GROUP_KEY_ID__NUM_OF
+#define bcmbal_interface_key_id_all_properties BCMBAL_INTERFACE_KEY_ID__NUM_OF
+#define bcmbal_interface_cfg_id_all_properties BCMBAL_INTERFACE_CFG_ID__NUM_OF
+#define bcmbal_interface_stat_id_all_properties BCMBAL_INTERFACE_STAT_ID__NUM_OF
+#define bcmbal_interface_ind_id_all_properties BCMBAL_INTERFACE_IND_ID__NUM_OF
+#define bcmbal_packet_cfg_id_all_properties BCMBAL_PACKET_CFG_ID__NUM_OF
+#define bcmbal_packet_key_id_all_properties BCMBAL_PACKET_KEY_ID__NUM_OF
+#define bcmbal_packet_ind_id_all_properties BCMBAL_PACKET_IND_ID__NUM_OF
+#define bcmbal_subscriber_terminal_key_id_all_properties BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID__NUM_OF
+#define bcmbal_subscriber_terminal_cfg_id_all_properties BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID__NUM_OF
+#define bcmbal_subscriber_terminal_stat_id_all_properties BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID__NUM_OF
+#define bcmbal_subscriber_terminal_ind_id_all_properties BCMBAL_SUBSCRIBER_TERMINAL_IND_ID__NUM_OF
+#define bcmbal_tm_queue_key_id_all_properties BCMBAL_TM_QUEUE_KEY_ID__NUM_OF
+#define bcmbal_tm_queue_cfg_id_all_properties BCMBAL_TM_QUEUE_CFG_ID__NUM_OF
+#define bcmbal_tm_queue_stat_id_all_properties BCMBAL_TM_QUEUE_STAT_ID__NUM_OF
+#define bcmbal_tm_queue_ind_id_all_properties BCMBAL_TM_QUEUE_IND_ID__NUM_OF
+#define bcmbal_tm_sched_key_id_all_properties BCMBAL_TM_SCHED_KEY_ID__NUM_OF
+#define bcmbal_tm_sched_cfg_id_all_properties BCMBAL_TM_SCHED_CFG_ID__NUM_OF
+#define bcmbal_tm_sched_ind_id_all_properties BCMBAL_TM_SCHED_IND_ID__NUM_OF
+
+/* The following are required for the API Init/Set/etc macros */
+#define bcmbal_obj_id__begin BCMBAL_OBJ_ID__BEGIN
+#define bcmbal_obj_id_access_terminal BCMBAL_OBJ_ID_ACCESS_TERMINAL
+#define bcmbal_obj_id_flow BCMBAL_OBJ_ID_FLOW
+#define bcmbal_obj_id_group BCMBAL_OBJ_ID_GROUP
+#define bcmbal_obj_id_interface BCMBAL_OBJ_ID_INTERFACE
+#define bcmbal_obj_id_packet BCMBAL_OBJ_ID_PACKET
+#define bcmbal_obj_id_subscriber_terminal BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL
+#define bcmbal_obj_id_tm_queue BCMBAL_OBJ_ID_TM_QUEUE
+#define bcmbal_obj_id_tm_sched BCMBAL_OBJ_ID_TM_SCHED
+#define bcmbal_obj_id__num_of BCMBAL_OBJ_ID__NUM_OF
+#define bcmbal_access_terminal_auto_id__begin BCMBAL_ACCESS_TERMINAL_AUTO_ID__BEGIN
+#define bcmbal_access_terminal_auto_id_ind BCMBAL_ACCESS_TERMINAL_AUTO_ID_IND
+#define bcmbal_access_terminal_auto_id__num_of BCMBAL_ACCESS_TERMINAL_AUTO_ID__NUM_OF
+#define bcmbal_flow_auto_id__begin BCMBAL_FLOW_AUTO_ID__BEGIN
+#define bcmbal_flow_auto_id_ind BCMBAL_FLOW_AUTO_ID_IND
+#define bcmbal_flow_auto_id__num_of BCMBAL_FLOW_AUTO_ID__NUM_OF
+#define bcmbal_interface_auto_id__begin BCMBAL_INTERFACE_AUTO_ID__BEGIN
+#define bcmbal_interface_auto_id_ind BCMBAL_INTERFACE_AUTO_ID_IND
+#define bcmbal_interface_auto_id__num_of BCMBAL_INTERFACE_AUTO_ID__NUM_OF
+#define bcmbal_packet_auto_id__begin BCMBAL_PACKET_AUTO_ID__BEGIN
+#define bcmbal_packet_auto_id_ind BCMBAL_PACKET_AUTO_ID_IND
+#define bcmbal_packet_auto_id__num_of BCMBAL_PACKET_AUTO_ID__NUM_OF
+#define bcmbal_subscriber_terminal_auto_id__begin BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID__BEGIN
+#define bcmbal_subscriber_terminal_auto_id_ind BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID_IND
+#define bcmbal_subscriber_terminal_auto_id__num_of BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID__NUM_OF
+#define bcmbal_tm_queue_auto_id__begin BCMBAL_TM_QUEUE_AUTO_ID__BEGIN
+#define bcmbal_tm_queue_auto_id_ind BCMBAL_TM_QUEUE_AUTO_ID_IND
+#define bcmbal_tm_queue_auto_id__num_of BCMBAL_TM_QUEUE_AUTO_ID__NUM_OF
+#define bcmbal_tm_sched_auto_id__begin BCMBAL_TM_SCHED_AUTO_ID__BEGIN
+#define bcmbal_tm_sched_auto_id_ind BCMBAL_TM_SCHED_AUTO_ID_IND
+#define bcmbal_tm_sched_auto_id__num_of BCMBAL_TM_SCHED_AUTO_ID__NUM_OF
+#define bcmbal_access_terminal_key_id_access_term_id BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID
+#define bcmbal_access_terminal_key_id__num_of BCMBAL_ACCESS_TERMINAL_KEY_ID__NUM_OF
+#define bcmbal_access_terminal_cfg_id_admin_state BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE
+#define bcmbal_access_terminal_cfg_id_oper_status BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS
+#define bcmbal_access_terminal_cfg_id_iwf_mode BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE
+#define bcmbal_access_terminal_cfg_id__num_of BCMBAL_ACCESS_TERMINAL_CFG_ID__NUM_OF
+#define bcmbal_access_terminal_ind_id_admin_state BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE
+#define bcmbal_access_terminal_ind_id_oper_status BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS
+#define bcmbal_access_terminal_ind_id_iwf_mode BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE
+#define bcmbal_access_terminal_ind_id__num_of BCMBAL_ACCESS_TERMINAL_IND_ID__NUM_OF
+#define bcmbal_flow_key_id_flow_id BCMBAL_FLOW_KEY_ID_FLOW_ID
+#define bcmbal_flow_key_id_flow_type BCMBAL_FLOW_KEY_ID_FLOW_TYPE
+#define bcmbal_flow_key_id__num_of BCMBAL_FLOW_KEY_ID__NUM_OF
+#define bcmbal_flow_cfg_id_admin_state BCMBAL_FLOW_CFG_ID_ADMIN_STATE
+#define bcmbal_flow_cfg_id_oper_status BCMBAL_FLOW_CFG_ID_OPER_STATUS
+#define bcmbal_flow_cfg_id_access_int_id BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID
+#define bcmbal_flow_cfg_id_network_int_id BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID
+#define bcmbal_flow_cfg_id_sub_term_id BCMBAL_FLOW_CFG_ID_SUB_TERM_ID
+#define bcmbal_flow_cfg_id_sub_term_uni_idx BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX
+#define bcmbal_flow_cfg_id_svc_port_id BCMBAL_FLOW_CFG_ID_SVC_PORT_ID
+#define bcmbal_flow_cfg_id_agg_port_id BCMBAL_FLOW_CFG_ID_AGG_PORT_ID
+#define bcmbal_flow_cfg_id_resolve_mac BCMBAL_FLOW_CFG_ID_RESOLVE_MAC
+#define bcmbal_flow_cfg_id_classifier BCMBAL_FLOW_CFG_ID_CLASSIFIER
+#define bcmbal_flow_cfg_id_action BCMBAL_FLOW_CFG_ID_ACTION
+#define bcmbal_flow_cfg_id_sla BCMBAL_FLOW_CFG_ID_SLA
+#define bcmbal_flow_cfg_id_cookie BCMBAL_FLOW_CFG_ID_COOKIE
+#define bcmbal_flow_cfg_id_priority BCMBAL_FLOW_CFG_ID_PRIORITY
+#define bcmbal_flow_cfg_id_group_id BCMBAL_FLOW_CFG_ID_GROUP_ID
+#define bcmbal_flow_cfg_id_queue BCMBAL_FLOW_CFG_ID_QUEUE
+#define bcmbal_flow_cfg_id__num_of BCMBAL_FLOW_CFG_ID__NUM_OF
+#define bcmbal_flow_stat_id_rx_packets BCMBAL_FLOW_STAT_ID_RX_PACKETS
+#define bcmbal_flow_stat_id_rx_bytes BCMBAL_FLOW_STAT_ID_RX_BYTES
+#define bcmbal_flow_stat_id_tx_packets BCMBAL_FLOW_STAT_ID_TX_PACKETS
+#define bcmbal_flow_stat_id_tx_bytes BCMBAL_FLOW_STAT_ID_TX_BYTES
+#define bcmbal_flow_stat_id__num_of BCMBAL_FLOW_STAT_ID__NUM_OF
+#define bcmbal_flow_ind_id_admin_state BCMBAL_FLOW_IND_ID_ADMIN_STATE
+#define bcmbal_flow_ind_id_oper_status BCMBAL_FLOW_IND_ID_OPER_STATUS
+#define bcmbal_flow_ind_id_access_int_id BCMBAL_FLOW_IND_ID_ACCESS_INT_ID
+#define bcmbal_flow_ind_id_network_int_id BCMBAL_FLOW_IND_ID_NETWORK_INT_ID
+#define bcmbal_flow_ind_id_sub_term_id BCMBAL_FLOW_IND_ID_SUB_TERM_ID
+#define bcmbal_flow_ind_id_svc_port_id BCMBAL_FLOW_IND_ID_SVC_PORT_ID
+#define bcmbal_flow_ind_id_agg_port_id BCMBAL_FLOW_IND_ID_AGG_PORT_ID
+#define bcmbal_flow_ind_id_resolve_mac BCMBAL_FLOW_IND_ID_RESOLVE_MAC
+#define bcmbal_flow_ind_id_base_tc_id BCMBAL_FLOW_IND_ID_BASE_TC_ID
+#define bcmbal_flow_ind_id_classifier BCMBAL_FLOW_IND_ID_CLASSIFIER
+#define bcmbal_flow_ind_id_action BCMBAL_FLOW_IND_ID_ACTION
+#define bcmbal_flow_ind_id_sla BCMBAL_FLOW_IND_ID_SLA
+#define bcmbal_flow_ind_id_cookie BCMBAL_FLOW_IND_ID_COOKIE
+#define bcmbal_flow_ind_id_priority BCMBAL_FLOW_IND_ID_PRIORITY
+#define bcmbal_flow_ind_id__num_of BCMBAL_FLOW_IND_ID__NUM_OF
+#define bcmbal_group_key_id_group_id BCMBAL_GROUP_KEY_ID_GROUP_ID
+#define bcmbal_group_key_id__num_of BCMBAL_GROUP_KEY_ID__NUM_OF
+#define bcmbal_group_cfg_id_members_cmd BCMBAL_GROUP_CFG_ID_MEMBERS_CMD
+#define bcmbal_group_cfg_id_members BCMBAL_GROUP_CFG_ID_MEMBERS
+#define bcmbal_group_cfg_id_cookie BCMBAL_GROUP_CFG_ID_COOKIE
+#define bcmbal_group_cfg_id_flows BCMBAL_GROUP_CFG_ID_FLOWS
+#define bcmbal_group_cfg_id_owner BCMBAL_GROUP_CFG_ID_OWNER
+#define bcmbal_group_cfg_id__num_of BCMBAL_GROUP_CFG_ID__NUM_OF
+#define bcmbal_interface_key_id_intf_id BCMBAL_INTERFACE_KEY_ID_INTF_ID
+#define bcmbal_interface_key_id_intf_type BCMBAL_INTERFACE_KEY_ID_INTF_TYPE
+#define bcmbal_interface_key_id__num_of BCMBAL_INTERFACE_KEY_ID__NUM_OF
+#define bcmbal_interface_cfg_id_admin_state BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE
+#define bcmbal_interface_cfg_id_oper_status BCMBAL_INTERFACE_CFG_ID_OPER_STATUS
+#define bcmbal_interface_cfg_id_min_data_agg_port_id BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID
+#define bcmbal_interface_cfg_id_min_data_svc_port_id BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID
+#define bcmbal_interface_cfg_id_transceiver_type BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE
+#define bcmbal_interface_cfg_id_ds_miss_mode BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE
+#define bcmbal_interface_cfg_id_mtu BCMBAL_INTERFACE_CFG_ID_MTU
+#define bcmbal_interface_cfg_id_flow_control BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL
+#define bcmbal_interface_cfg_id_ds_tm BCMBAL_INTERFACE_CFG_ID_DS_TM
+#define bcmbal_interface_cfg_id_us_tm BCMBAL_INTERFACE_CFG_ID_US_TM
+#define bcmbal_interface_cfg_id_sub_term_id_list BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST
+#define bcmbal_interface_cfg_id__num_of BCMBAL_INTERFACE_CFG_ID__NUM_OF
+#define bcmbal_interface_stat_id_rx_packets BCMBAL_INTERFACE_STAT_ID_RX_PACKETS
+#define bcmbal_interface_stat_id_rx_bytes BCMBAL_INTERFACE_STAT_ID_RX_BYTES
+#define bcmbal_interface_stat_id_tx_packets BCMBAL_INTERFACE_STAT_ID_TX_PACKETS
+#define bcmbal_interface_stat_id_tx_bytes BCMBAL_INTERFACE_STAT_ID_TX_BYTES
+#define bcmbal_interface_stat_id__num_of BCMBAL_INTERFACE_STAT_ID__NUM_OF
+#define bcmbal_interface_ind_id_admin_state BCMBAL_INTERFACE_IND_ID_ADMIN_STATE
+#define bcmbal_interface_ind_id_oper_status BCMBAL_INTERFACE_IND_ID_OPER_STATUS
+#define bcmbal_interface_ind_id_min_data_agg_port_id BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID
+#define bcmbal_interface_ind_id_min_data_svc_port_id BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID
+#define bcmbal_interface_ind_id_transceiver_type BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE
+#define bcmbal_interface_ind_id_ds_miss_mode BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE
+#define bcmbal_interface_ind_id_mtu BCMBAL_INTERFACE_IND_ID_MTU
+#define bcmbal_interface_ind_id_flow_control BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL
+#define bcmbal_interface_ind_id_ds_tm BCMBAL_INTERFACE_IND_ID_DS_TM
+#define bcmbal_interface_ind_id_us_tm BCMBAL_INTERFACE_IND_ID_US_TM
+#define bcmbal_interface_ind_id__num_of BCMBAL_INTERFACE_IND_ID__NUM_OF
+#define bcmbal_packet_key_id_reserved BCMBAL_PACKET_KEY_ID_RESERVED
+#define bcmbal_packet_key_id_packet_send_dest BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST
+#define bcmbal_packet_key_id__num_of BCMBAL_PACKET_KEY_ID__NUM_OF
+#define bcmbal_packet_cfg_id_flow_id BCMBAL_PACKET_CFG_ID_FLOW_ID
+#define bcmbal_packet_cfg_id_flow_type BCMBAL_PACKET_CFG_ID_FLOW_TYPE
+#define bcmbal_packet_cfg_id_intf_id BCMBAL_PACKET_CFG_ID_INTF_ID
+#define bcmbal_packet_cfg_id_intf_type BCMBAL_PACKET_CFG_ID_INTF_TYPE
+#define bcmbal_packet_cfg_id_svc_port BCMBAL_PACKET_CFG_ID_SVC_PORT
+#define bcmbal_packet_cfg_id_flow_cookie BCMBAL_PACKET_CFG_ID_FLOW_COOKIE
+#define bcmbal_packet_cfg_id_pkt BCMBAL_PACKET_CFG_ID_PKT
+#define bcmbal_packet_cfg_id__num_of BCMBAL_PACKET_CFG_ID__NUM_OF
+#define bcmbal_packet_ind_id_flow_id BCMBAL_PACKET_IND_ID_FLOW_ID
+#define bcmbal_packet_ind_id_flow_type BCMBAL_PACKET_IND_ID_FLOW_TYPE
+#define bcmbal_packet_ind_id_intf_id BCMBAL_PACKET_IND_ID_INTF_ID
+#define bcmbal_packet_ind_id_intf_type BCMBAL_PACKET_IND_ID_INTF_TYPE
+#define bcmbal_packet_ind_id_svc_port BCMBAL_PACKET_IND_ID_SVC_PORT
+#define bcmbal_packet_ind_id_flow_cookie BCMBAL_PACKET_IND_ID_FLOW_COOKIE
+#define bcmbal_packet_ind_id_pkt BCMBAL_PACKET_IND_ID_PKT
+#define bcmbal_packet_ind_id__num_of BCMBAL_PACKET_IND_ID__NUM_OF
+#define bcmbal_subscriber_terminal_key_id_sub_term_id BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID
+#define bcmbal_subscriber_terminal_key_id_intf_id BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID
+#define bcmbal_subscriber_terminal_key_id__num_of BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID__NUM_OF
+#define bcmbal_subscriber_terminal_cfg_id_admin_state BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE
+#define bcmbal_subscriber_terminal_cfg_id_oper_status BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS
+#define bcmbal_subscriber_terminal_cfg_id_serial_number BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER
+#define bcmbal_subscriber_terminal_cfg_id_password BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD
+#define bcmbal_subscriber_terminal_cfg_id_registration_id BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID
+#define bcmbal_subscriber_terminal_cfg_id_svc_port_id BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID
+#define bcmbal_subscriber_terminal_cfg_id_mac_address BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS
+#define bcmbal_subscriber_terminal_cfg_id_ds_tm BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM
+#define bcmbal_subscriber_terminal_cfg_id_us_tm BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM
+#define bcmbal_subscriber_terminal_cfg_id_svc_port_id_list BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST
+#define bcmbal_subscriber_terminal_cfg_id_agg_port_id_list BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST
+#define bcmbal_subscriber_terminal_cfg_id__num_of BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID__NUM_OF
+#define bcmbal_subscriber_terminal_stat_id_rx_packets BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS
+#define bcmbal_subscriber_terminal_stat_id_rx_bytes BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES
+#define bcmbal_subscriber_terminal_stat_id_tx_packets BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS
+#define bcmbal_subscriber_terminal_stat_id_tx_bytes BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES
+#define bcmbal_subscriber_terminal_stat_id__num_of BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID__NUM_OF
+#define bcmbal_subscriber_terminal_ind_id_admin_state BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE
+#define bcmbal_subscriber_terminal_ind_id_oper_status BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS
+#define bcmbal_subscriber_terminal_ind_id_serial_number BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER
+#define bcmbal_subscriber_terminal_ind_id_password BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD
+#define bcmbal_subscriber_terminal_ind_id_registration_id BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID
+#define bcmbal_subscriber_terminal_ind_id_svc_port_id BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID
+#define bcmbal_subscriber_terminal_ind_id_mac_address BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS
+#define bcmbal_subscriber_terminal_ind_id_ds_tm BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM
+#define bcmbal_subscriber_terminal_ind_id_us_tm BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM
+#define bcmbal_subscriber_terminal_ind_id__num_of BCMBAL_SUBSCRIBER_TERMINAL_IND_ID__NUM_OF
+#define bcmbal_tm_queue_key_id_sched_id BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID
+#define bcmbal_tm_queue_key_id_sched_dir BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR
+#define bcmbal_tm_queue_key_id_id BCMBAL_TM_QUEUE_KEY_ID_ID
+#define bcmbal_tm_queue_key_id__num_of BCMBAL_TM_QUEUE_KEY_ID__NUM_OF
+#define bcmbal_tm_queue_cfg_id_priority BCMBAL_TM_QUEUE_CFG_ID_PRIORITY
+#define bcmbal_tm_queue_cfg_id_weight BCMBAL_TM_QUEUE_CFG_ID_WEIGHT
+#define bcmbal_tm_queue_cfg_id_rate BCMBAL_TM_QUEUE_CFG_ID_RATE
+#define bcmbal_tm_queue_cfg_id_bac BCMBAL_TM_QUEUE_CFG_ID_BAC
+#define bcmbal_tm_queue_cfg_id_creation_mode BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE
+#define bcmbal_tm_queue_cfg_id_ref_count BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT
+#define bcmbal_tm_queue_cfg_id__num_of BCMBAL_TM_QUEUE_CFG_ID__NUM_OF
+#define bcmbal_tm_queue_stat_id_packets_ok BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK
+#define bcmbal_tm_queue_stat_id_bytes_ok BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK
+#define bcmbal_tm_queue_stat_id_packets_discarded BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED
+#define bcmbal_tm_queue_stat_id_bytes_discarded BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED
+#define bcmbal_tm_queue_stat_id__num_of BCMBAL_TM_QUEUE_STAT_ID__NUM_OF
+#define bcmbal_tm_queue_ind_id_ret BCMBAL_TM_QUEUE_IND_ID_RET
+#define bcmbal_tm_queue_ind_id__num_of BCMBAL_TM_QUEUE_IND_ID__NUM_OF
+#define bcmbal_tm_sched_key_id_dir BCMBAL_TM_SCHED_KEY_ID_DIR
+#define bcmbal_tm_sched_key_id_id BCMBAL_TM_SCHED_KEY_ID_ID
+#define bcmbal_tm_sched_key_id__num_of BCMBAL_TM_SCHED_KEY_ID__NUM_OF
+#define bcmbal_tm_sched_cfg_id_owner BCMBAL_TM_SCHED_CFG_ID_OWNER
+#define bcmbal_tm_sched_cfg_id_sched_type BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE
+#define bcmbal_tm_sched_cfg_id_sched_parent BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT
+#define bcmbal_tm_sched_cfg_id_sched_child_type BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE
+#define bcmbal_tm_sched_cfg_id_rate BCMBAL_TM_SCHED_CFG_ID_RATE
+#define bcmbal_tm_sched_cfg_id_tcont_sla BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA
+#define bcmbal_tm_sched_cfg_id_creation_mode BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE
+#define bcmbal_tm_sched_cfg_id_queues BCMBAL_TM_SCHED_CFG_ID_QUEUES
+#define bcmbal_tm_sched_cfg_id_sub_scheds BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS
+#define bcmbal_tm_sched_cfg_id_num_priorities BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES
+#define bcmbal_tm_sched_cfg_id__num_of BCMBAL_TM_SCHED_CFG_ID__NUM_OF
+#define bcmbal_tm_sched_ind_id_ret BCMBAL_TM_SCHED_IND_ID_RET
+#define bcmbal_tm_sched_ind_id__num_of BCMBAL_TM_SCHED_IND_ID__NUM_OF
+
+/** Checks whether the given object type has the given tag.
+ *
+ * \return true if the given object has the given tag, false otherwise
+ */
+bcmos_bool bcmbal_obj_has_tag(bcmbal_obj_id obj, bcmbal_obj_tag tag);
+
+#define BCMBAL_OBJ_ID_ANY ((bcmbal_obj_id) UINT16_MAX)
+
+/** @} */
+#endif /* BAL_MODEL_IDS_H_ */
diff --git a/bal_release/src/common/include/bal_model_types.h b/bal_release/src/common/include/bal_model_types.h
new file mode 100644
index 0000000..af683fc
--- /dev/null
+++ b/bal_release/src/common/include/bal_model_types.h
@@ -0,0 +1,1154 @@
+#ifndef BAL_MODEL_TYPES
+#define BAL_MODEL_TYPES
+
+#include <bcmos_system.h>
+#include "bal_obj.h"
+
+/** \defgroup object_model_data_types BAL Object Model Data Types
+ * @{
+ */
+typedef uint32_t bcmbal_access_id; /**< bcmbal_access_id: typed alias for a 32-bit unsigned integer. */
+typedef uint16_t bcmbal_aggregation_port_id; /**< bcmbal_aggregation_port_id: typed alias for a 16-bit unsigned integer. */
+typedef uint64_t bcmbal_cookie; /**< bcmbal_cookie: typed alias for a 64-bit unsigned integer. */
+typedef uint32_t bcmbal_intf_id; /**< bcmbal_intf_id: typed alias for a 32-bit unsigned integer. */
+typedef uint32_t bcmbal_sub_id; /**< bcmbal_sub_id: typed alias for a 32-bit unsigned integer. */
+#define BCMBAL_SUB_ID_UNKNOWN ((bcmbal_sub_id) 65535UL)
+typedef uint32_t bcmbal_flow_id; /**< bcmbal_flow_id: typed alias for a 32-bit unsigned integer. */
+typedef uint32_t bcmbal_group_id; /**< bcmbal_group_id: typed alias for a 32-bit unsigned integer. */
+typedef uint16_t bcmbal_service_port_id; /**< bcmbal_service_port_id: typed alias for a 16-bit unsigned integer. */
+typedef uint32_t bcmbal_tm_sched_id; /**< bcmbal_tm_sched_id: typed alias for a 32-bit unsigned integer. */
+#define BCMBAL_TM_SCHED_ID_UNKNOWN ((bcmbal_tm_sched_id) 65535UL)
+typedef uint8_t bcmbal_tm_queue_id; /**< bcmbal_tm_queue_id: typed alias for a 8-bit unsigned integer. */
+typedef uint8_t bcmbal_percent; /**< bcmbal_percent: typed alias for a 8-bit unsigned integer. */
+typedef uint8_t bcmbal_tm_priority; /**< bcmbal_tm_priority: typed alias for a 8-bit unsigned integer. */
+typedef uint16_t bcmbal_tm_sched_id_index; /**< bcmbal_tm_sched_id_index: typed alias for a 16-bit unsigned integer. */
+typedef uint8_t bcmbal_tm_weight; /**< bcmbal_tm_weight: typed alias for a 8-bit unsigned integer. */
+
+/** action ID.
+ */
+typedef enum bcmbal_action_id
+{
+ BCMBAL_ACTION_ID_NONE = 0,
+ BCMBAL_ACTION_ID_CMDS_BITMASK = 0x0001, /**< Commands bitmask. */
+ BCMBAL_ACTION_ID_O_VID = 0x0002, /**< Outer vid. */
+ BCMBAL_ACTION_ID_O_PBITS = 0x0004, /**< Outer pbits. */
+ BCMBAL_ACTION_ID_O_TPID = 0x0008, /**< Outer tpid. */
+ BCMBAL_ACTION_ID_I_VID = 0x0010, /**< Inner vid. */
+ BCMBAL_ACTION_ID_I_PBITS = 0x0020, /**< Inner pbits. */
+ BCMBAL_ACTION_ID_I_TPID = 0x0040, /**< Inner tpid. */
+ BCMBAL_ACTION_ID_ALL = 0x007F /**< All fields */
+} bcmbal_action_id;
+
+/** action_cmd_id.
+ */
+typedef enum bcmbal_action_cmd_id
+{
+ BCMBAL_ACTION_CMD_ID_NONE = 0,
+ BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG = 0x0001, /**< Add outer tag. */
+ BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG = 0x0002, /**< Remove outer tag. */
+ BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG = 0x0004, /**< Translate outer tag. */
+ BCMBAL_ACTION_CMD_ID_XLATE_TWO_TAGS = 0x0008, /**< Translate two tags. */
+ BCMBAL_ACTION_CMD_ID_DISCARD_DS_BCAST = 0x0010, /**< Used to satisfy TR-156 Issue 3 R-111 */
+ BCMBAL_ACTION_CMD_ID_DISCARD_DS_UNKNOWN = 0x0020, /**< Used to satisfy TR-156 Issue 3 R-109 */
+ BCMBAL_ACTION_CMD_ID_ADD_TWO_TAGS = 0x0040, /**< Add two tags. */
+ BCMBAL_ACTION_CMD_ID_REMOVE_TWO_TAGS = 0x0080, /**< Remove two tags. */
+ BCMBAL_ACTION_CMD_ID_REMARK_PBITS = 0x0100, /**< Set the outer tag pbits */
+ BCMBAL_ACTION_CMD_ID_COPY_PBITS = 0x0200, /**< Copy the inner pbits to outer pbits */
+ BCMBAL_ACTION_CMD_ID_REVERSE_COPY_PBITS = 0x0400, /**< Copy the outer pbits to inner pbits */
+ BCMBAL_ACTION_CMD_ID_DSCP_TO_PBITS = 0x0800, /**< Copy the L4 DSCP to outer pbits */
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST = 0x1000 /**< Not a valid action for a group object member */
+} bcmbal_action_cmd_id;
+
+/** classifier ID.
+ */
+typedef enum bcmbal_classifier_id
+{
+ BCMBAL_CLASSIFIER_ID_NONE = 0,
+ BCMBAL_CLASSIFIER_ID_O_TPID = 0x0001, /**< Outer TPID of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_O_VID = 0x0002, /**< Outer VID of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_I_TPID = 0x0004, /**< Inner TPID of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_I_VID = 0x0008, /**< Inner VID of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_O_PBITS = 0x0010, /**< Outer PBITS of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_I_PBITS = 0x0020, /**< Inner PBITS of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_ETHER_TYPE = 0x0040, /**< Ethertype of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_DST_MAC = 0x0080, /**< Destination MAC address of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_SRC_MAC = 0x0100, /**< Source MAC address of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_IP_PROTO = 0x0200, /**< IP protocol of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_DST_IP = 0x0400, /**< Destination IP address of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_SRC_IP = 0x0800, /**< Source IP address of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_SRC_PORT = 0x1000, /**< Source port of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_DST_PORT = 0x2000, /**< Destination port of the packet to be classified */
+ BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE = 0x4000, /**< The tag type of the ingress packets */
+ BCMBAL_CLASSIFIER_ID_ALL = 0x7FFF /**< All fields */
+} bcmbal_classifier_id;
+
+/** Packet tag type.
+ */
+typedef enum bcmbal_pkt_tag_type
+{
+ BCMBAL_PKT_TAG_TYPE_NONE = 0,
+ BCMBAL_PKT_TAG_TYPE_UNTAGGED = 0x0001, /**< Untagged. */
+ BCMBAL_PKT_TAG_TYPE_SINGLE_TAG = 0x0002, /**< Single tag. */
+ BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG = 0x0004 /**< Double tag. */
+} bcmbal_pkt_tag_type;
+
+/** Generic enable/disable enumeration
+ */
+typedef enum bcmbal_control
+{
+ BCMBAL_CONTROL_DISABLE = 0, /**< disable. */
+ BCMBAL_CONTROL_ENABLE = 1, /**< enable. */
+ BCMBAL_CONTROL__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_control;
+
+/** Destination type.
+ */
+typedef enum bcmbal_dest_type
+{
+ BCMBAL_DEST_TYPE_NNI = 1, /**< for packets being sent to the NNI */
+ BCMBAL_DEST_TYPE_SUB_TERM = 2, /**< for packets being sent to a subscriber terminal */
+ BCMBAL_DEST_TYPE_HOST = 3 /**< for packet indications received from NNI or SUB_TERM and being sent to the host */
+} bcmbal_dest_type;
+
+/** Downstrean action for unknown packets.
+ */
+typedef enum bcmbal_ds_miss_mode
+{
+ BCMBAL_DS_MISS_MODE_DISCARD = 0, /**< Discard. */
+ BCMBAL_DS_MISS_MODE_BROADCAST = 1, /**< Broadcast. */
+ BCMBAL_DS_MISS_MODE_VID = 2, /**< Vid. */
+ BCMBAL_DS_MISS_MODE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_ds_miss_mode;
+
+/** Extra BW Eligibility Type
+ */
+typedef enum bcmbal_extra_bw_eligibility_type
+{
+ BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NONE = 0, /**< None */
+ BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NOT_ASSURED= 1, /**< Not assured */
+ BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_BEST_EFFORT= 2, /**< Best effort */
+ BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_extra_bw_eligibility_type;
+
+/** Flow Type.
+ */
+typedef enum bcmbal_flow_type
+{
+ BCMBAL_FLOW_TYPE_UPSTREAM = 1, /**< Upstream flow */
+ BCMBAL_FLOW_TYPE_DOWNSTREAM = 2, /**< Downstream Flow */
+ BCMBAL_FLOW_TYPE_BROADCAST = 3, /**< Broadcast Flow */
+ BCMBAL_FLOW_TYPE_MULTICAST = 4 /**< Multicast Flow */
+} bcmbal_flow_type;
+
+/** Member operation type.
+ */
+typedef enum bcmbal_group_member_cmd
+{
+ BCMBAL_GROUP_MEMBER_CMD_ADD_MEMBERS = 1, /**< Add new members. */
+ BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS = 2, /**< Remove existing members. */
+ BCMBAL_GROUP_MEMBER_CMD_SET_MEMBERS = 3 /**< Replace members with new set. */
+} bcmbal_group_member_cmd;
+
+/** owner of the group
+ */
+typedef enum bcmbal_group_owner
+{
+ BCMBAL_GROUP_OWNER_NONE = 0, /**< no owner */
+ BCMBAL_GROUP_OWNER_MULTICAST = 1, /**< used as multicast group */
+ BCMBAL_GROUP_OWNER_UNICAST = 2, /**< used as unicast group */
+ BCMBAL_GROUP_OWNER__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_group_owner;
+
+/** Interface type.
+ */
+typedef enum bcmbal_intf_type
+{
+ BCMBAL_INTF_TYPE_NNI = 0, /**< NNI Interface. */
+ BCMBAL_INTF_TYPE_PON = 1, /**< POIN Interface. */
+ BCMBAL_INTF_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_intf_type;
+
+/** Interworking Function Mode.
+ */
+typedef enum bcmbal_iwf_mode
+{
+ BCMBAL_IWF_MODE_DIRECT_MAPPING = 0, /**< Direct mapping. */
+ BCMBAL_IWF_MODE_PER_FLOW = 1, /**< Per flow . */
+ BCMBAL_IWF_MODE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_iwf_mode;
+
+/** SLA ID.
+ */
+typedef enum bcmbal_sla_id
+{
+ BCMBAL_SLA_ID_NONE = 0,
+ BCMBAL_SLA_ID_MIN_RATE = 0x0001, /**< The minimal rate for this flow, in kilobits per second (optional) */
+ BCMBAL_SLA_ID_MAX_RATE = 0x0002, /**< The maximum rate for this flow, in kilobits per second (optional) */
+ BCMBAL_SLA_ID_ALL = 0x0003 /**< All fields */
+} bcmbal_sla_id;
+
+/** Admin state values for access terminal object
+ */
+typedef enum bcmbal_state
+{
+ BCMBAL_STATE_UP = 1, /**< Admin state up */
+ BCMBAL_STATE_DOWN = 2, /**< Admin state down */
+ BCMBAL_STATE_TESTING = 3 /**< Admin state testing */
+} bcmbal_state;
+
+/** Oper status values
+ */
+typedef enum bcmbal_status
+{
+ BCMBAL_STATUS_UP = 1, /**< Oper status up */
+ BCMBAL_STATUS_DOWN = 2, /**< Oper status down */
+ BCMBAL_STATUS_TESTING = 3, /**< Oper status testing */
+ BCMBAL_STATUS_NOT_PRESENT = 4, /**< Oper status not present */
+ BCMBAL_STATUS_LOWER_LAYER_DOWN = 5, /**< Oper status lower layer down */
+ BCMBAL_STATUS_UNKNOWN = 6 /**< Oper status unknown */
+} bcmbal_status;
+
+/** Buffer Admission Control Type
+ */
+typedef enum bcmbal_tm_bac_type
+{
+ BCMBAL_TM_BAC_TYPE_TAILDROP = 0, /**< Taildrop */
+ BCMBAL_TM_BAC_TYPE_WTAILDROP = 1, /**< Weighted taildrop */
+ BCMBAL_TM_BAC_TYPE_RED = 2, /**< Random Early Discard */
+ BCMBAL_TM_BAC_TYPE_WRED = 3, /**< Weighted Random Early Discard */
+ BCMBAL_TM_BAC_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_bac_type;
+
+/** TM Creation Mode
+ */
+typedef enum bcmbal_tm_creation_mode
+{
+ BCMBAL_TM_CREATION_MODE_MANUAL = 0, /**< tm object created manually */
+ BCMBAL_TM_CREATION_MODE_AUTO = 1, /**< tm object created automatically */
+ BCMBAL_TM_CREATION_MODE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_creation_mode;
+
+/** Scheduling Level for the Children TM
+ */
+typedef enum bcmbal_tm_sched_child_type
+{
+ BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE = 0, /**< Queue-level scheduler */
+ BCMBAL_TM_SCHED_CHILD_TYPE_SCHED = 1, /**< Scheduler-level scheduler */
+ BCMBAL_TM_SCHED_CHILD_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_child_type;
+
+/** Traffic Direction
+ */
+typedef enum bcmbal_tm_sched_dir
+{
+ BCMBAL_TM_SCHED_DIR_US = 1, /**< Upstream */
+ BCMBAL_TM_SCHED_DIR_DS = 2 /**< Downstream */
+} bcmbal_tm_sched_dir;
+
+/** TM Scheduler Owner Type
+ */
+typedef enum bcmbal_tm_sched_owner_type
+{
+ BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED = 0, /**< Undefined */
+ BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE = 1, /**< Interface */
+ BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM = 2, /**< Subscriber terminal */
+ BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT = 3, /**< TM scheduler is owned by aggregation port */
+ BCMBAL_TM_SCHED_OWNER_TYPE_UNI = 4, /**< TM scheduler is owned by UNI port */
+ BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL = 5, /**< Other unspecified owner */
+ BCMBAL_TM_SCHED_OWNER_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_owner_type;
+
+/** tm_sched_owner agg_port ID.
+ */
+typedef enum bcmbal_tm_sched_owner_agg_port_id
+{
+ BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_NONE = 0,
+ BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_INTF_ID = 0x0001, /**< PON interface id */
+ BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_SUB_TERM_ID = 0x0002, /**< Subscriber terminal id */
+ BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_AGG_PORT_ID = 0x0004, /**< Aggregation port id */
+ BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_ALL = 0x0007 /**< All fields */
+} bcmbal_tm_sched_owner_agg_port_id;
+
+/** tm_sched_parent ID.
+ */
+typedef enum bcmbal_tm_sched_parent_id
+{
+ BCMBAL_TM_SCHED_PARENT_ID_NONE = 0,
+ BCMBAL_TM_SCHED_PARENT_ID_SCHED_ID = 0x0001, /**< Parent scheduler id */
+ BCMBAL_TM_SCHED_PARENT_ID_PRIORITY = 0x0002, /**< Priority */
+ BCMBAL_TM_SCHED_PARENT_ID_WEIGHT = 0x0004, /**< Weight */
+ BCMBAL_TM_SCHED_PARENT_ID_ALL = 0x0007 /**< All fields */
+} bcmbal_tm_sched_parent_id;
+
+/** Scheduler Type
+ */
+typedef enum bcmbal_tm_sched_type
+{
+ BCMBAL_TM_SCHED_TYPE_NONE = 0, /**< NO scheduling */
+ BCMBAL_TM_SCHED_TYPE_WFQ = 1, /**< Weighted Fair Queue */
+ BCMBAL_TM_SCHED_TYPE_SP = 2, /**< Strict Priority */
+ BCMBAL_TM_SCHED_TYPE_SP_WFQ = 3, /**< Hybrid SP + WFQ */
+ BCMBAL_TM_SCHED_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_tm_sched_type;
+
+/** tm_shaping ID.
+ */
+typedef enum bcmbal_tm_shaping_id
+{
+ BCMBAL_TM_SHAPING_ID_NONE = 0,
+ BCMBAL_TM_SHAPING_ID_SBR = 0x0001, /**< Sustained Bit Rate (kbps) */
+ BCMBAL_TM_SHAPING_ID_PBR = 0x0002, /**< Peak Bit Rate (kbps) */
+ BCMBAL_TM_SHAPING_ID_BURST = 0x0004, /**< Max Burst Bytes at Peak Bit Rate */
+ BCMBAL_TM_SHAPING_ID_ALL = 0x0007 /**< All fields */
+} bcmbal_tm_shaping_id;
+
+/** tm_tcont_sla ID.
+ */
+typedef enum bcmbal_tm_tcont_sla_id
+{
+ BCMBAL_TM_TCONT_SLA_ID_NONE = 0,
+ BCMBAL_TM_TCONT_SLA_ID_EXTRA_BW_ELIG = 0x0001, /**< Extra BW eligibility type */
+ BCMBAL_TM_TCONT_SLA_ID_NRT_CBR = 0x0002, /**< NRT CBR */
+ BCMBAL_TM_TCONT_SLA_ID_RT_CBR = 0x0004, /**< RT_CBR */
+ BCMBAL_TM_TCONT_SLA_ID_RT_PROFILE = 0x0008, /**< RT Profile */
+ BCMBAL_TM_TCONT_SLA_ID_NRT_PROFILE = 0x0010, /**< NRT Profile */
+ BCMBAL_TM_TCONT_SLA_ID_ALL = 0x001F /**< All fields */
+} bcmbal_tm_tcont_sla_id;
+
+/** Transceiver types
+ */
+typedef enum bcmbal_trx_type
+{
+ BCMBAL_TRX_TYPE_GPON_SPS_43_48 = 0, /**< gpon_sps_43_48. */
+ BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321 = 1, /**< gpon_sps_sog_4321. */
+ BCMBAL_TRX_TYPE_GPON_LTE_3680_M = 2, /**< gpon_lte_3680_m. */
+ BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS = 3, /**< gpon_source_photonics. */
+ BCMBAL_TRX_TYPE_GPON_LTE_3680_P = 4, /**< gpon_lte_3680_p. */
+ BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC = 5, /**< xgpon_lth_7222_pc. */
+ BCMBAL_TRX_TYPE_XGPON_LTH_7226_PC = 6, /**< xgpon_lth_7226_pc. */
+ BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC = 7, /**< xgpon_lth_5302_pc. */
+ BCMBAL_TRX_TYPE__NUM_OF /**< Number of enum entries, not an entry itself. */
+} bcmbal_trx_type;
+
+#define bcmbal_action_id_none BCMBAL_ACTION_ID_NONE
+#define bcmbal_action_id_cmds_bitmask BCMBAL_ACTION_ID_CMDS_BITMASK
+#define bcmbal_action_id_o_vid BCMBAL_ACTION_ID_O_VID
+#define bcmbal_action_id_o_pbits BCMBAL_ACTION_ID_O_PBITS
+#define bcmbal_action_id_o_tpid BCMBAL_ACTION_ID_O_TPID
+#define bcmbal_action_id_i_vid BCMBAL_ACTION_ID_I_VID
+#define bcmbal_action_id_i_pbits BCMBAL_ACTION_ID_I_PBITS
+#define bcmbal_action_id_i_tpid BCMBAL_ACTION_ID_I_TPID
+#define bcmbal_action_id_all BCMBAL_ACTION_ID_ALL
+#define bcmbal_classifier_id_none BCMBAL_CLASSIFIER_ID_NONE
+#define bcmbal_classifier_id_o_tpid BCMBAL_CLASSIFIER_ID_O_TPID
+#define bcmbal_classifier_id_o_vid BCMBAL_CLASSIFIER_ID_O_VID
+#define bcmbal_classifier_id_i_tpid BCMBAL_CLASSIFIER_ID_I_TPID
+#define bcmbal_classifier_id_i_vid BCMBAL_CLASSIFIER_ID_I_VID
+#define bcmbal_classifier_id_o_pbits BCMBAL_CLASSIFIER_ID_O_PBITS
+#define bcmbal_classifier_id_i_pbits BCMBAL_CLASSIFIER_ID_I_PBITS
+#define bcmbal_classifier_id_ether_type BCMBAL_CLASSIFIER_ID_ETHER_TYPE
+#define bcmbal_classifier_id_dst_mac BCMBAL_CLASSIFIER_ID_DST_MAC
+#define bcmbal_classifier_id_src_mac BCMBAL_CLASSIFIER_ID_SRC_MAC
+#define bcmbal_classifier_id_ip_proto BCMBAL_CLASSIFIER_ID_IP_PROTO
+#define bcmbal_classifier_id_dst_ip BCMBAL_CLASSIFIER_ID_DST_IP
+#define bcmbal_classifier_id_src_ip BCMBAL_CLASSIFIER_ID_SRC_IP
+#define bcmbal_classifier_id_src_port BCMBAL_CLASSIFIER_ID_SRC_PORT
+#define bcmbal_classifier_id_dst_port BCMBAL_CLASSIFIER_ID_DST_PORT
+#define bcmbal_classifier_id_pkt_tag_type BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE
+#define bcmbal_classifier_id_all BCMBAL_CLASSIFIER_ID_ALL
+#define bcmbal_sla_id_none BCMBAL_SLA_ID_NONE
+#define bcmbal_sla_id_min_rate BCMBAL_SLA_ID_MIN_RATE
+#define bcmbal_sla_id_max_rate BCMBAL_SLA_ID_MAX_RATE
+#define bcmbal_sla_id_all BCMBAL_SLA_ID_ALL
+#define bcmbal_tm_sched_owner_agg_port_id_none BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_NONE
+#define bcmbal_tm_sched_owner_agg_port_id_intf_id BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_INTF_ID
+#define bcmbal_tm_sched_owner_agg_port_id_sub_term_id BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_SUB_TERM_ID
+#define bcmbal_tm_sched_owner_agg_port_id_agg_port_id BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_AGG_PORT_ID
+#define bcmbal_tm_sched_owner_agg_port_id_all BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_ALL
+#define bcmbal_tm_sched_parent_id_none BCMBAL_TM_SCHED_PARENT_ID_NONE
+#define bcmbal_tm_sched_parent_id_sched_id BCMBAL_TM_SCHED_PARENT_ID_SCHED_ID
+#define bcmbal_tm_sched_parent_id_priority BCMBAL_TM_SCHED_PARENT_ID_PRIORITY
+#define bcmbal_tm_sched_parent_id_weight BCMBAL_TM_SCHED_PARENT_ID_WEIGHT
+#define bcmbal_tm_sched_parent_id_all BCMBAL_TM_SCHED_PARENT_ID_ALL
+#define bcmbal_tm_shaping_id_none BCMBAL_TM_SHAPING_ID_NONE
+#define bcmbal_tm_shaping_id_sbr BCMBAL_TM_SHAPING_ID_SBR
+#define bcmbal_tm_shaping_id_pbr BCMBAL_TM_SHAPING_ID_PBR
+#define bcmbal_tm_shaping_id_burst BCMBAL_TM_SHAPING_ID_BURST
+#define bcmbal_tm_shaping_id_all BCMBAL_TM_SHAPING_ID_ALL
+#define bcmbal_tm_tcont_sla_id_none BCMBAL_TM_TCONT_SLA_ID_NONE
+#define bcmbal_tm_tcont_sla_id_extra_bw_elig BCMBAL_TM_TCONT_SLA_ID_EXTRA_BW_ELIG
+#define bcmbal_tm_tcont_sla_id_nrt_cbr BCMBAL_TM_TCONT_SLA_ID_NRT_CBR
+#define bcmbal_tm_tcont_sla_id_rt_cbr BCMBAL_TM_TCONT_SLA_ID_RT_CBR
+#define bcmbal_tm_tcont_sla_id_rt_profile BCMBAL_TM_TCONT_SLA_ID_RT_PROFILE
+#define bcmbal_tm_tcont_sla_id_nrt_profile BCMBAL_TM_TCONT_SLA_ID_NRT_PROFILE
+#define bcmbal_tm_tcont_sla_id_all BCMBAL_TM_TCONT_SLA_ID_ALL
+
+/** action.
+ */
+typedef struct bcmbal_action
+{
+ bcmbal_action_id presence_mask; /**< Presence Mask. */
+ bcmbal_action_cmd_id cmds_bitmask; /**< Commands bitmask. */
+ uint16_t o_vid; /**< Outer vid. */
+ uint8_t o_pbits; /**< Outer pbits. */
+ uint16_t o_tpid; /**< Outer tpid. */
+ uint16_t i_vid; /**< Inner vid. */
+ uint8_t i_pbits; /**< Inner pbits. */
+ uint16_t i_tpid; /**< Inner tpid. */
+} bcmbal_action;
+
+/** Variable-length list of aggregation_port_id.
+ */
+typedef struct bcmbal_aggregation_port_id_list_u8
+{
+ uint8_t len; /**< List length. */
+ bcmbal_aggregation_port_id *val; /**< List contents. */
+} bcmbal_aggregation_port_id_list_u8;
+
+/** classifier.
+ */
+typedef struct bcmbal_classifier
+{
+ bcmbal_classifier_id presence_mask; /**< Presence Mask. */
+ uint16_t o_tpid; /**< Outer TPID of the packet to be classified */
+ uint16_t o_vid; /**< Outer VID of the packet to be classified */
+ uint16_t i_tpid; /**< Inner TPID of the packet to be classified */
+ uint16_t i_vid; /**< Inner VID of the packet to be classified */
+ uint8_t o_pbits; /**< Outer PBITS of the packet to be classified */
+ uint8_t i_pbits; /**< Inner PBITS of the packet to be classified */
+ uint16_t ether_type; /**< Ethertype of the packet to be classified */
+ bcmos_mac_address dst_mac; /**< Destination MAC address of the packet to be classified */
+ bcmos_mac_address src_mac; /**< Source MAC address of the packet to be classified */
+ uint8_t ip_proto; /**< IP protocol of the packet to be classified */
+ bcmos_ipv4_address dst_ip; /**< Destination IP address of the packet to be classified */
+ bcmos_ipv4_address src_ip; /**< Source IP address of the packet to be classified */
+ uint16_t src_port; /**< Source port of the packet to be classified */
+ uint16_t dst_port; /**< Destination port of the packet to be classified */
+ bcmbal_pkt_tag_type pkt_tag_type; /**< The tag type of the ingress packets */
+} bcmbal_classifier;
+
+/** Packet destination.
+ */
+typedef struct bcmbal_dest
+{
+ bcmbal_dest_type type; /**< packet destination. */
+ union
+ {
+ struct
+ {
+ bcmbal_intf_id int_id; /**< Interface ID. */
+ } nni;
+
+ struct
+ {
+ bcmbal_sub_id sub_term_id; /**< Subscriber terminal ID. */
+ uint16_t sub_term_uni; /**< Subscriber terminal UNI. */
+ uint16_t int_id; /**< Interface ID. */
+ } sub_term;
+ } u;
+} bcmbal_dest;
+
+/** Variable-length list of flow_id.
+ */
+typedef struct bcmbal_flow_id_list_u32
+{
+ uint32_t len; /**< List length. */
+ bcmbal_flow_id *val; /**< List contents. */
+} bcmbal_flow_id_list_u32;
+
+/** Queue Reference
+ */
+typedef struct bcmbal_tm_queue_ref
+{
+ bcmbal_tm_sched_id sched_id; /**< Scheduler (tm_sched) ID */
+ bcmbal_tm_queue_id queue_id; /**< Queue ID */
+} bcmbal_tm_queue_ref;
+
+/** Group Member Info.
+ */
+typedef struct bcmbal_group_member_info
+{
+ bcmbal_intf_id intf_id; /**< Access interface id for this member */
+ bcmbal_service_port_id svc_port_id; /**< The multicast "GEM" for this member */
+ bcmbal_action action; /**< VLAN actions */
+ bcmbal_tm_queue_ref queue; /**< Egress queue */
+} bcmbal_group_member_info;
+
+/** Variable-length list of group_member_info.
+ */
+typedef struct bcmbal_group_member_info_list_u16
+{
+ uint16_t len; /**< List length. */
+ bcmbal_group_member_info *val; /**< List contents. */
+} bcmbal_group_member_info_list_u16;
+
+/** Password.
+ */
+typedef struct bcmbal_password
+{
+ uint8_t arr[10]; /**< Array. */
+} bcmbal_password;
+
+/** Registration id.
+ */
+typedef struct bcmbal_registration_id
+{
+ uint8_t arr[36]; /**< ONU registration ID */
+} bcmbal_registration_id;
+
+/** Serial number.
+ */
+typedef struct bcmbal_serial_number
+{
+ uint8_t vendor_id[4]; /**< vendor id. */
+ uint8_t vendor_specific[4]; /**< vendor specific. */
+} bcmbal_serial_number;
+
+/** Variable-length list of service_port_id.
+ */
+typedef struct bcmbal_service_port_id_list_u8
+{
+ uint8_t len; /**< List length. */
+ bcmbal_service_port_id *val; /**< List contents. */
+} bcmbal_service_port_id_list_u8;
+
+/** SLA.
+ */
+typedef struct bcmbal_sla
+{
+ bcmbal_sla_id presence_mask; /**< Presence Mask. */
+ uint32_t min_rate; /**< The minimal rate for this flow, in kilobits per second (optional) */
+ uint32_t max_rate; /**< The maximum rate for this flow, in kilobits per second (optional) */
+} bcmbal_sla;
+
+/** Variable-length list of sub_id.
+ */
+typedef struct bcmbal_sub_id_list_u16
+{
+ uint16_t len; /**< List length. */
+ bcmbal_sub_id *val; /**< List contents. */
+} bcmbal_sub_id_list_u16;
+
+/** Random Early Discard Configuration
+ */
+typedef struct bcmbal_tm_red
+{
+ bcmbal_percent min_threshold; /**< Min threshold in percent of max queue size */
+ bcmbal_percent max_threshold; /**< Max threshold in percent of max queue size */
+ bcmbal_percent max_probability; /**< Discard probability for occupancy between min_threshold and max_threshold */
+} bcmbal_tm_red;
+
+/** Queue Buffer Admission Control
+ */
+typedef struct bcmbal_tm_bac
+{
+ bcmbal_tm_bac_type type; /**< Buffer Admission Control Type */
+ union
+ {
+ struct
+ {
+ uint32_t max_size; /**< max number of packets in the queue */
+ } taildrop;
+
+ struct
+ {
+ bcmbal_tm_red red; /**< Random Early Discard configuration */
+ } red;
+
+ struct
+ {
+ bcmbal_tm_red green; /**< Green Random Early Discard Configuration */
+ bcmbal_tm_red yellow; /**< Yellow Random Early Discard Configuration */
+ bcmbal_tm_red red; /**< Red Random Early Discard Configuration */
+ } wred;
+ } u;
+} bcmbal_tm_bac;
+
+/** Variable-length list of tm_queue_id.
+ */
+typedef struct bcmbal_tm_queue_id_list_u8
+{
+ uint8_t len; /**< List length. */
+ bcmbal_tm_queue_id *val; /**< List contents. */
+} bcmbal_tm_queue_id_list_u8;
+
+/** Variable-length list of tm_sched_id.
+ */
+typedef struct bcmbal_tm_sched_id_list_u8
+{
+ uint8_t len; /**< List length. */
+ bcmbal_tm_sched_id *val; /**< List contents. */
+} bcmbal_tm_sched_id_list_u8;
+
+/** TM Scheduler Owner
+ */
+typedef struct bcmbal_tm_sched_owner
+{
+ bcmbal_tm_sched_owner_type type; /**< Owner type */
+ union
+ {
+ struct
+ {
+ bcmbal_intf_type intf_type; /**< Interface Type */
+ bcmbal_intf_id intf_id; /**< Interface ID */
+ } interface;
+
+ struct
+ {
+ bcmbal_intf_id intf_id; /**< PON interface id */
+ bcmbal_sub_id sub_term_id; /**< Subscriber terminal ID */
+ } sub_term;
+
+ struct
+ {
+ bcmbal_tm_sched_owner_agg_port_id presence_mask; /**< Presence Mask. */
+ uint8_t intf_id; /**< PON interface id */
+ bcmbal_sub_id sub_term_id; /**< Subscriber terminal id */
+ bcmbal_aggregation_port_id agg_port_id; /**< Aggregation port id */
+ } agg_port;
+
+ struct
+ {
+ uint8_t intf_id; /**< PON interface id */
+ bcmbal_sub_id sub_term_id; /**< Subscriber terminal id */
+ uint8_t idx; /**< Index at subscriber terminal */
+ } uni;
+
+ struct
+ {
+ uint32_t idx; /**< Owner index */
+ } virtual;
+ } u;
+} bcmbal_tm_sched_owner;
+
+/** Scheduling Parent Connect Point
+ */
+typedef struct bcmbal_tm_sched_parent
+{
+ bcmbal_tm_sched_parent_id presence_mask; /**< Presence Mask. */
+ bcmbal_tm_sched_id sched_id; /**< Parent scheduler id */
+ bcmbal_tm_priority priority; /**< Priority */
+ bcmbal_tm_weight weight; /**< Weight */
+} bcmbal_tm_sched_parent;
+
+/** Shaping Parameters
+ */
+typedef struct bcmbal_tm_shaping
+{
+ bcmbal_tm_shaping_id presence_mask; /**< Presence Mask. */
+ uint32_t sbr; /**< Sustained Bit Rate (kbps) */
+ uint32_t pbr; /**< Peak Bit Rate (kbps) */
+ uint32_t burst; /**< Max Burst Bytes at Peak Bit Rate */
+} bcmbal_tm_shaping;
+
+/** ITU-PON Extended SLA Parameters
+ */
+typedef struct bcmbal_tm_tcont_sla
+{
+ bcmbal_tm_tcont_sla_id presence_mask; /**< Presence Mask. */
+ bcmbal_extra_bw_eligibility_type extra_bw_elig; /**< Extra BW eligibility type */
+ uint8_t nrt_cbr; /**< NRT CBR */
+ uint8_t rt_cbr; /**< RT_CBR */
+ uint8_t rt_profile; /**< RT Profile */
+ uint8_t nrt_profile; /**< NRT Profile */
+} bcmbal_tm_tcont_sla;
+
+/** Variable-length list of U8.
+ */
+typedef struct bcmbal_u8_list_u32
+{
+ uint32_t len; /**< List length. */
+ uint8_t *val; /**< List contents. */
+} bcmbal_u8_list_u32;
+
+/** Structure definition for the "key" group of the "access_terminal" object.
+ */
+typedef struct bcmbal_access_terminal_key
+{
+ bcmbal_access_id access_term_id; /**< Reserved (set to 0) */
+} bcmbal_access_terminal_key;
+
+/** Structure definition for the "cfg" group of the "access_terminal" object.
+ */
+typedef struct bcmbal_access_terminal_cfg_data
+{
+ bcmbal_state admin_state; /**< Administrative state */
+ bcmbal_status oper_status; /**< Operational status */
+ bcmbal_iwf_mode iwf_mode; /**< The interworking mode */
+} bcmbal_access_terminal_cfg_data;
+
+/** Transport message definition for "cfg" group of "access_terminal" object.
+ */
+typedef struct bcmbal_access_terminal_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_access_terminal_key key; /**< Object key. */
+ bcmbal_access_terminal_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_access_terminal_cfg;
+
+/** Structure definition for the "ind" group of the "access_terminal" object.
+ */
+typedef struct bcmbal_access_terminal_ind_data
+{
+ bcmbal_state admin_state; /**< Current administrative state */
+ bcmbal_status oper_status; /**< Current operational status */
+ bcmbal_iwf_mode iwf_mode; /**< The interworking mode */
+} bcmbal_access_terminal_ind_data;
+
+/** Transport message definition for "ind" group of "access_terminal" object.
+ */
+typedef struct bcmbal_access_terminal_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_access_terminal_key key; /**< Object key. */
+ bcmbal_access_terminal_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_access_terminal_ind;
+
+/** Structure definition for the "key" group of the "flow" object.
+ */
+typedef struct bcmbal_flow_key
+{
+ bcmbal_flow_id flow_id; /**< The ID of the flow object instance being referenced */
+ bcmbal_flow_type flow_type; /**< The type of the flow, Upstream, Downstream, Broadcast or Multicast */
+} bcmbal_flow_key;
+
+/** Structure definition for the "cfg" group of the "flow" object.
+ */
+typedef struct bcmbal_flow_cfg_data
+{
+ bcmbal_state admin_state; /**< Administrative state */
+ bcmbal_status oper_status; /**< Operational status */
+ bcmbal_intf_id access_int_id; /**< The ID of the subscriber side interface; i.e. PON */
+ bcmbal_intf_id network_int_id; /**< The ID of the network side interface; i.e. NNI */
+ bcmbal_sub_id sub_term_id; /**< The ID of the subsccriber terminal device */
+ uint8_t sub_term_uni_idx; /**< The index of the subsccriber terminal uni port the flow is related to */
+ bcmbal_service_port_id svc_port_id; /**< The ID of the service port (for GPON/XGPON - GEM ID) */
+ bcmbal_aggregation_port_id agg_port_id; /**< The ID of the aggregate port (for GPON/XGPON - ALLOC ID) */
+ bcmos_bool resolve_mac; /**< A flag indicating if the MAC address table should be used in DS GEM resolution */
+ bcmbal_classifier classifier; /**< The classifier for this flow */
+ bcmbal_action action; /**< The action associated with the flow */
+ bcmbal_sla sla; /**< SLA parameters for this flow */
+ bcmbal_cookie cookie; /**< Application cookie */
+ uint16_t priority; /**< Priority for this flow in case of multiple match. */
+ bcmbal_group_id group_id; /**< RW - The multicast group associated with this flow, valid for type MULTICAST only */
+ bcmbal_tm_queue_ref queue; /**< Egress queue */
+} bcmbal_flow_cfg_data;
+
+/** Transport message definition for "cfg" group of "flow" object.
+ */
+typedef struct bcmbal_flow_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_flow_key key; /**< Object key. */
+ bcmbal_flow_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_flow_cfg;
+
+/** Structure definition for the "stat" group of the "flow" object.
+ */
+typedef struct bcmbal_flow_stat_data
+{
+ uint64_t rx_packets; /**< Received packets. */
+ uint64_t rx_bytes; /**< Received bytes. */
+ uint64_t tx_packets; /**< Transmitted packets. */
+ uint64_t tx_bytes; /**< Transmitted bytes. */
+} bcmbal_flow_stat_data;
+
+/** Transport message definition for "stat" group of "flow" object.
+ */
+typedef struct bcmbal_flow_stat
+{
+ bcmbal_stat hdr; /**< Transport header. */
+ bcmbal_flow_key key; /**< Object key. */
+ bcmbal_flow_stat_data data; /**< All properties that must be set by the user. */
+} bcmbal_flow_stat;
+
+/** Structure definition for the "ind" group of the "flow" object.
+ */
+typedef struct bcmbal_flow_ind_data
+{
+ bcmbal_state admin_state; /**< Administrative state */
+ bcmbal_status oper_status; /**< Operational Status */
+ uint16_t access_int_id; /**< The ID of the subscriber side interface; i.e. PON */
+ uint16_t network_int_id; /**< The ID of the network side interface; i.e. NNI */
+ uint32_t sub_term_id; /**< The ID of the subsccriber terminal device */
+ uint16_t svc_port_id; /**< The ID of the service port (for GPON/XGPON - GEM ID) */
+ uint16_t agg_port_id; /**< The ID of the aggregate port (for GPON/XGPON - ALLOC ID) */
+ bcmos_bool resolve_mac; /**< A flag indicating if the MAC address table should be used in DS GEM resolution */
+ uint16_t base_tc_id; /**< The base index of the TC object(s) to be used for this flow */
+ bcmbal_classifier classifier; /**< The classifier for this flow */
+ bcmbal_action action; /**< The action associated with the flow */
+ bcmbal_sla sla; /**< SLA parameters for this flow */
+ uint32_t cookie; /**< Application cookie */
+ uint16_t priority; /**< Priority for this flow in case of multiple match. */
+} bcmbal_flow_ind_data;
+
+/** Transport message definition for "ind" group of "flow" object.
+ */
+typedef struct bcmbal_flow_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_flow_key key; /**< Object key. */
+ bcmbal_flow_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_flow_ind;
+
+/** Structure definition for the "key" group of the "group" object.
+ */
+typedef struct bcmbal_group_key
+{
+ bcmbal_group_id group_id; /**< The ID of the group object instance being referenced */
+} bcmbal_group_key;
+
+/** Structure definition for the "cfg" group of the "group" object.
+ */
+typedef struct bcmbal_group_cfg_data
+{
+ bcmbal_group_member_cmd members_cmd; /**< Membership operation commands. */
+ bcmbal_group_member_info_list_u16 members; /**< The list of members associated with this group */
+ bcmbal_cookie cookie; /**< Application cookie */
+ bcmbal_flow_id_list_u32 flows; /**< List of flows associated with this group */
+ bcmbal_group_owner owner; /**< Owner of the group. */
+} bcmbal_group_cfg_data;
+
+/** Transport message definition for "cfg" group of "group" object.
+ */
+typedef struct bcmbal_group_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_group_key key; /**< Object key. */
+ bcmbal_group_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_group_cfg;
+
+/** Structure definition for the "key" group of the "interface" object.
+ */
+typedef struct bcmbal_interface_key
+{
+ uint32_t intf_id; /**< intf_id. */
+ bcmbal_intf_type intf_type; /**< intf_type. */
+} bcmbal_interface_key;
+
+/** Structure definition for the "cfg" group of the "interface" object.
+ */
+typedef struct bcmbal_interface_cfg_data
+{
+ bcmbal_state admin_state; /**< Administrative state */
+ bcmbal_status oper_status; /**< Operational status */
+ bcmbal_aggregation_port_id min_data_agg_port_id; /**< The minimum agg_port_id that is allowed in the system */
+ bcmbal_service_port_id min_data_svc_port_id; /**< The minimum svc_port_id that is allowed in the system */
+ bcmbal_trx_type transceiver_type; /**< The transceiver type used on an interface */
+ bcmbal_ds_miss_mode ds_miss_mode; /**< Defines the action to take for unknown downstream packets */
+ uint16_t mtu; /**< The MTU for an interface */
+ bcmbal_control flow_control; /**< Flow control enable or disable */
+ bcmbal_tm_sched_id ds_tm; /**< Downstream scheduler and shaper */
+ bcmbal_tm_sched_id us_tm; /**< Upstream scheduler and shaper */
+ bcmbal_sub_id_list_u16 sub_term_id_list; /**< A list of subscriber terminal ids configured on this interface */
+} bcmbal_interface_cfg_data;
+
+/** Transport message definition for "cfg" group of "interface" object.
+ */
+typedef struct bcmbal_interface_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_interface_key key; /**< Object key. */
+ bcmbal_interface_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_interface_cfg;
+
+/** Structure definition for the "stat" group of the "interface" object.
+ */
+typedef struct bcmbal_interface_stat_data
+{
+ uint64_t rx_packets; /**< Recieved packets. */
+ uint64_t rx_bytes; /**< Received bytes. */
+ uint64_t tx_packets; /**< Transmitted packets. */
+ uint64_t tx_bytes; /**< Transmitted bytes. */
+} bcmbal_interface_stat_data;
+
+/** Transport message definition for "stat" group of "interface" object.
+ */
+typedef struct bcmbal_interface_stat
+{
+ bcmbal_stat hdr; /**< Transport header. */
+ bcmbal_interface_key key; /**< Object key. */
+ bcmbal_interface_stat_data data; /**< All properties that must be set by the user. */
+} bcmbal_interface_stat;
+
+/** Structure definition for the "ind" group of the "interface" object.
+ */
+typedef struct bcmbal_interface_ind_data
+{
+ bcmbal_state admin_state; /**< Current administrative state */
+ bcmbal_status oper_status; /**< Current operational state */
+ uint16_t min_data_agg_port_id; /**< The minimum agg_port_id that is allowed in the system */
+ uint16_t min_data_svc_port_id; /**< The minimum svc_port_id that is allowed in the system */
+ bcmbal_trx_type transceiver_type; /**< The transceiver type used on an interface */
+ bcmbal_ds_miss_mode ds_miss_mode; /**< Defines the action to take for DS unknown packets */
+ uint16_t mtu; /**< The MTU for an interface */
+ bcmbal_control flow_control; /**< Flow control enable or disable */
+ bcmbal_tm_sched_id ds_tm; /**< Downstream scheduler and shaper */
+ bcmbal_tm_sched_id us_tm; /**< Upstream scheduler and shaper */
+} bcmbal_interface_ind_data;
+
+/** Transport message definition for "ind" group of "interface" object.
+ */
+typedef struct bcmbal_interface_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_interface_key key; /**< Object key. */
+ bcmbal_interface_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_interface_ind;
+
+/** Structure definition for the "key" group of the "packet" object.
+ */
+typedef struct bcmbal_packet_key
+{
+ uint32_t reserved; /**< Reserved key field. */
+ bcmbal_dest packet_send_dest; /**< Packet destination. */
+} bcmbal_packet_key;
+
+/** Structure definition for the "cfg" group of the "packet" object.
+ */
+typedef struct bcmbal_packet_cfg_data
+{
+ bcmbal_flow_id flow_id; /**< N/A for sending a packet */
+ bcmbal_flow_type flow_type; /**< Flow Type. */
+ bcmbal_intf_id intf_id; /**< Interface ID. */
+ bcmbal_intf_type intf_type; /**< Interface Type. */
+ bcmbal_service_port_id svc_port; /**< N/A for sending a packet */
+ bcmbal_cookie flow_cookie; /**< N/A for sending a packet */
+ bcmbal_u8_list_u32 pkt; /**< Packet Data. */
+} bcmbal_packet_cfg_data;
+
+/** Transport message definition for "cfg" group of "packet" object.
+ */
+typedef struct bcmbal_packet_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_packet_key key; /**< Object key. */
+ bcmbal_packet_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_packet_cfg;
+
+/** Structure definition for the "ind" group of the "packet" object.
+ */
+typedef struct bcmbal_packet_ind_data
+{
+ bcmbal_flow_id flow_id; /**< N/A for sending a packet */
+ bcmbal_flow_type flow_type; /**< Flow Type. */
+ bcmbal_intf_id intf_id; /**< Interface ID. */
+ bcmbal_intf_type intf_type; /**< Interface Type. */
+ bcmbal_service_port_id svc_port; /**< N/A for sending a packet */
+ bcmbal_cookie flow_cookie; /**< N/A for sending a packet */
+ bcmbal_u8_list_u32 pkt; /**< Packet Data. */
+} bcmbal_packet_ind_data;
+
+/** Transport message definition for "ind" group of "packet" object.
+ */
+typedef struct bcmbal_packet_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_packet_key key; /**< Object key. */
+ bcmbal_packet_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_packet_ind;
+
+/** Structure definition for the "key" group of the "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_key
+{
+ bcmbal_sub_id sub_term_id; /**< sub_term_id. */
+ bcmbal_intf_id intf_id; /**< intf_id. */
+} bcmbal_subscriber_terminal_key;
+
+/** Structure definition for the "cfg" group of the "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_cfg_data
+{
+ bcmbal_state admin_state; /**< Administrative state */
+ bcmbal_status oper_status; /**< Operational status */
+ bcmbal_serial_number serial_number; /**< The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal */
+ bcmbal_password password; /**< The password of a GPON subscriber terminal */
+ bcmbal_registration_id registration_id; /**< ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal */
+ bcmbal_service_port_id svc_port_id; /**< The management service port ID (for PON, the ONU ID) */
+ bcmos_mac_address mac_address; /**< The Ethernet MAC address of an EPON subscriber terminal */
+ bcmbal_tm_sched_id ds_tm; /**< Downstream scheduler and shaper */
+ bcmbal_tm_sched_id us_tm; /**< Upstream scheduler and shaper */
+ bcmbal_service_port_id_list_u8 svc_port_id_list; /**< A list of bearer traffic svc_port_ids associated with this subscriber terminal */
+ bcmbal_aggregation_port_id_list_u8 agg_port_id_list; /**< A list of aggr_port_ids associated with this subscriber terminal */
+} bcmbal_subscriber_terminal_cfg_data;
+
+/** Transport message definition for "cfg" group of "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_subscriber_terminal_key key; /**< Object key. */
+ bcmbal_subscriber_terminal_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_subscriber_terminal_cfg;
+
+/** Structure definition for the "stat" group of the "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_stat_data
+{
+ uint64_t rx_packets; /**< Received packets on specified object */
+ uint64_t rx_bytes; /**< Received bytes on specified object */
+ uint64_t tx_packets; /**< Transmitted packets on specified object */
+ uint64_t tx_bytes; /**< Transmittted bytes on specified object */
+} bcmbal_subscriber_terminal_stat_data;
+
+/** Transport message definition for "stat" group of "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_stat
+{
+ bcmbal_stat hdr; /**< Transport header. */
+ bcmbal_subscriber_terminal_key key; /**< Object key. */
+ bcmbal_subscriber_terminal_stat_data data; /**< All properties that must be set by the user. */
+} bcmbal_subscriber_terminal_stat;
+
+/** Structure definition for the "ind" group of the "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_ind_data
+{
+ bcmbal_state admin_state; /**< Current administrative state */
+ bcmbal_status oper_status; /**< Current operational status */
+ bcmbal_serial_number serial_number; /**< The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal */
+ bcmbal_password password; /**< The password of a GPON subscriber terminal */
+ bcmbal_registration_id registration_id; /**< ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal */
+ uint16_t svc_port_id; /**< The service port ID (for PON, the ONU ID) */
+ bcmos_mac_address mac_address; /**< The Ethernet MAC address of an epon subscriber terminal */
+ bcmbal_tm_sched_id ds_tm; /**< Downstream scheduler and shaper */
+ bcmbal_tm_sched_id us_tm; /**< Upstream scheduler and shaper */
+} bcmbal_subscriber_terminal_ind_data;
+
+/** Transport message definition for "ind" group of "subscriber_terminal"
+ * object.
+ */
+typedef struct bcmbal_subscriber_terminal_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_subscriber_terminal_key key; /**< Object key. */
+ bcmbal_subscriber_terminal_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_subscriber_terminal_ind;
+
+/** Structure definition for the "key" group of the "tm_queue" object.
+ */
+typedef struct bcmbal_tm_queue_key
+{
+ bcmbal_tm_sched_id sched_id; /**< Scheduler that owns the queue */
+ bcmbal_tm_sched_dir sched_dir; /**< sched dir. */
+ bcmbal_tm_queue_id id; /**< Queue id */
+} bcmbal_tm_queue_key;
+
+/** Structure definition for the "cfg" group of the "tm_queue" object.
+ */
+typedef struct bcmbal_tm_queue_cfg_data
+{
+ bcmbal_tm_priority priority; /**< Scheduling priority */
+ bcmbal_tm_weight weight; /**< Scheduling weight */
+ bcmbal_tm_shaping rate; /**< Rate shaping parameters */
+ bcmbal_tm_bac bac; /**< Buffer admission control */
+ bcmbal_tm_creation_mode creation_mode; /**< Creation mode */
+ uint8_t ref_count; /**< reference count (flows) */
+} bcmbal_tm_queue_cfg_data;
+
+/** Transport message definition for "cfg" group of "tm_queue" object.
+ */
+typedef struct bcmbal_tm_queue_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_tm_queue_key key; /**< Object key. */
+ bcmbal_tm_queue_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_tm_queue_cfg;
+
+/** Structure definition for the "stat" group of the "tm_queue" object.
+ */
+typedef struct bcmbal_tm_queue_stat_data
+{
+ uint64_t packets_ok; /**< Packets transmitted succewssfully */
+ uint64_t bytes_ok; /**< Bytes transmitted successfully */
+ uint64_t packets_discarded; /**< Packets discarded */
+ uint64_t bytes_discarded; /**< Bytes discarded */
+} bcmbal_tm_queue_stat_data;
+
+/** Transport message definition for "stat" group of "tm_queue" object.
+ */
+typedef struct bcmbal_tm_queue_stat
+{
+ bcmbal_stat hdr; /**< Transport header. */
+ bcmbal_tm_queue_key key; /**< Object key. */
+ bcmbal_tm_queue_stat_data data; /**< All properties that must be set by the user. */
+} bcmbal_tm_queue_stat;
+
+/** Structure definition for the "ind" group of the "tm_queue" object.
+ *
+ * Tm Queue Indication
+ */
+typedef struct bcmbal_tm_queue_ind_data
+{
+ uint32_t ret; /**< ret */
+} bcmbal_tm_queue_ind_data;
+
+/** Transport message definition for "ind" group of "tm_queue" object.
+ */
+typedef struct bcmbal_tm_queue_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_tm_queue_key key; /**< Object key. */
+ bcmbal_tm_queue_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_tm_queue_ind;
+
+/** Structure definition for the "key" group of the "tm_sched" object.
+ */
+typedef struct bcmbal_tm_sched_key
+{
+ bcmbal_tm_sched_dir dir; /**< Traffic direction */
+ bcmbal_tm_sched_id id; /**< ID */
+} bcmbal_tm_sched_key;
+
+/** Structure definition for the "cfg" group of the "tm_sched" object.
+ */
+typedef struct bcmbal_tm_sched_cfg_data
+{
+ bcmbal_tm_sched_owner owner; /**< owner. */
+ bcmbal_tm_sched_type sched_type; /**< Scheduler type */
+ bcmbal_tm_sched_parent sched_parent; /**< Scheduling parameters for parent scheduler */
+ bcmbal_tm_sched_child_type sched_child_type; /**< Scheduling level for children tm */
+ bcmbal_tm_shaping rate; /**< Rate shaping parameters */
+ bcmbal_tm_tcont_sla tcont_sla; /**< Additional SLA parameters for agg_port owner */
+ bcmbal_tm_creation_mode creation_mode; /**< Creation mode */
+ bcmbal_tm_queue_id_list_u8 queues; /**< Subsidiary queues */
+ bcmbal_tm_sched_id_list_u8 sub_scheds; /**< Subsidiary schedulers */
+ uint8_t num_priorities; /**< Max number of strict priority scheduling elements */
+} bcmbal_tm_sched_cfg_data;
+
+/** Transport message definition for "cfg" group of "tm_sched" object.
+ */
+typedef struct bcmbal_tm_sched_cfg
+{
+ bcmbal_cfg hdr; /**< Transport header. */
+ bcmbal_tm_sched_key key; /**< Object key. */
+ bcmbal_tm_sched_cfg_data data; /**< All properties that must be set by the user. */
+} bcmbal_tm_sched_cfg;
+
+/** Structure definition for the "ind" group of the "tm_sched" object.
+ *
+ * Tm Sched Indication
+ */
+typedef struct bcmbal_tm_sched_ind_data
+{
+ uint32_t ret; /**< ret */
+} bcmbal_tm_sched_ind_data;
+
+/** Transport message definition for "ind" group of "tm_sched" object.
+ */
+typedef struct bcmbal_tm_sched_ind
+{
+ bcmbal_auto hdr; /**< Transport header. */
+ bcmbal_tm_sched_key key; /**< Object key. */
+ bcmbal_tm_sched_ind_data data; /**< All properties that must be set by the user. */
+} bcmbal_tm_sched_ind;
+
+/** @} */
+#endif /* BAL_MODEL_TYPES */
diff --git a/bal_release/src/common/include/bal_msg.h b/bal_release/src/common/include/bal_msg.h
new file mode 100644
index 0000000..4ea85c5
--- /dev/null
+++ b/bal_release/src/common/include/bal_msg.h
@@ -0,0 +1,349 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/* Define the top level Doxygen groups. */
+
+/**
+ * @defgroup core BAL Core Engine
+ *
+ * @defgroup apps BAL Utils
+ *
+ * @defgroup lib BAL Libraries
+ *
+ */
+
+/**
+ * @file bal_msg.h
+ *
+ * @brief Include files and miscellaneous macros for the BAL messaging
+ *
+ */
+
+#ifndef BALMSG_H
+#define BALMSG_H
+
+#include <bal_objs.h>
+#include <bal_msg_type.h>
+
+
+/*******************************************************************
+ **
+ ** BAL message header helpers
+ **
+ *******************************************************************
+ */
+
+/*
+ * Underlying msg_send timeout units in uS (micro seconds)
+ */
+#define BCMBAL_MSG_TIMEOUT_1_SEC (1000000)
+
+/*
+ * Get a pointer to the message payload given the bcmos_msg pointer
+ */
+static inline void *bcmbal_payload_ptr_get(bal_comm_msg_hdr *_m)
+{
+ /* payload starts from BAL communication header */
+ return (void *)_m;
+}
+
+/*
+ * Get a pointer to the BAL header given the message payload pointer
+ */
+static inline bal_comm_msg_hdr *bcmbal_bal_hdr_get(void *_msg_payload_ptr)
+{
+ /* payload starts from BAL communication header */
+ return (bal_comm_msg_hdr *)_msg_payload_ptr;
+}
+
+/*
+ * Get a pointer to the BAL header given the bcmos header pointer
+ */
+static inline bal_comm_msg_hdr *bcmbal_bal_hdr_get_by_bcmos_hdr(bcmos_msg *m)
+{
+ return container_of(m, bal_comm_msg_hdr, m);
+}
+
+/*
+ * Get a pointer to the BCMOS header given the message payload pointer
+ */
+static inline bcmos_msg *bcmbal_bcmos_hdr_get(void *_msg_payload_ptr)
+{
+ return &(bcmbal_bal_hdr_get(_msg_payload_ptr)->m);
+}
+
+/*
+ * Set the BAL header parameters given the message payload pointer
+ */
+static inline void bcmbal_msg_hdr_set(void *_msg_payload_ptr,
+ bcmos_msg_id _type_major,
+ bcmbal_msg_type _type_minor,
+ bal_subsystem _sender_subsys,
+ bcmbal_obj_id _msg_id_obj,
+ uint16_t _msg_id_oper,
+ uint32_t _ex_id)
+{
+ bcmos_msg *os_msg = bcmbal_bcmos_hdr_get(_msg_payload_ptr);
+ bal_comm_msg_hdr *bal_hdr = bcmbal_bal_hdr_get(_msg_payload_ptr);
+
+ /*
+ * set up the bcmos_msg header fields
+ */
+ os_msg->data = (void *)((char *)(bcmbal_bcmos_hdr_get(_msg_payload_ptr)) + sizeof(bcmos_msg));
+ os_msg->start = os_msg->data;
+ os_msg->type = _type_major;
+ os_msg->instance = 0;
+ os_msg->sender = BCMOS_MODULE_ID_NONE; /* doesn't matter */
+
+ /*
+ * set up the bal msg header fields
+ */
+ bal_hdr->version_major = BAL_HDR_VERSION_MAJOR;
+ bal_hdr->version_minor = BAL_HDR_VERSION_MINOR;
+ bal_hdr->msg_type = _type_minor;
+ bal_hdr->msg_id = ((bal_hdr->msg_id & 0x0000FFFF) | ((_msg_id_oper & 0x0000FFFF) << 16));
+ bal_hdr->msg_id = ((bal_hdr->msg_id & 0xFFFF0000) | (_msg_id_obj & 0x0000FFFF));
+ bal_hdr->ex_id = _ex_id;
+ bal_hdr->sender = _sender_subsys;
+ bal_hdr->timestamp = bcmos_timestamp();
+}
+
+/*
+ * Get the sender field in the BAL header given the message pointer
+ */
+static inline bal_subsystem bcmbal_sender_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bal_hdr_get(_msg_payload_ptr)->sender;
+}
+
+/*
+ * Set the sender field in the BAL header given the message pointer
+ */
+static inline void bcmbal_sender_set(void *_msg_payload_ptr, bal_subsystem _sender_subsys)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->sender = _sender_subsys;
+}
+
+/*
+ * Get the top level type field in the BAL header given the message pointer
+ */
+static inline bcmos_msg_id bcmbal_type_major_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bcmos_hdr_get(_msg_payload_ptr)->type;
+}
+
+/*
+ * Set the top level type field in the BAL header given the message pointer
+ */
+static inline void bcmbal_type_major_set(void *_msg_payload_ptr, bcmos_msg_id _type_major)
+{
+ bcmbal_bcmos_hdr_get(_msg_payload_ptr)->type = _type_major;
+}
+
+/*
+ * Get the inner type field in the BAL header given the message pointer
+ */
+static inline bcmbal_msg_type bcmbal_type_minor_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_type;
+}
+
+/*
+ * Set the inner type field in the BAL header given the message pointer
+ */
+static inline void bcmbal_type_minor_set(void *_msg_payload_ptr, bcmbal_msg_type _type_minor)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_type = _type_minor;
+}
+
+
+/*
+ * Get the msg_id_oper field in the BAL header given the message pointer
+ */
+static inline uint16_t bcmbal_msg_id_oper_get(void *_msg_payload_ptr)
+{
+ return ((bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_id & 0xFFFF0000) >> 16);
+}
+
+/*
+ * Set the msg_id_oper field in the BAL header given the message pointer
+ */
+static inline void bcmbal_msg_id_oper_set(void *_msg_payload_ptr, uint16_t _msg_id_oper)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_id =
+ ((bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_id & 0x0000FFFF) | ((_msg_id_oper & 0x0000FFFF) << 16));
+}
+
+/*
+ * Get the msg_id_obj field in the BAL header given the message pointer
+ */
+static inline bcmbal_obj_id bcmbal_msg_id_obj_get(void *_msg_payload_ptr)
+{
+ return (bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_id & 0x0000FFFF );
+}
+
+/*
+ * Set the msg_id_obj field in the BAL header given the message pointer
+ */
+static inline void bcmbal_msg_id_obj_set(void *_msg_payload_ptr, bcmbal_obj_id _msg_id_obj)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_id =
+ ((bcmbal_bal_hdr_get(_msg_payload_ptr)->msg_id & 0xFFFF0000) | (_msg_id_obj & 0x0000FFFF));
+}
+
+/*
+ * Get the ex_id field in the BAL header given the message pointer
+ */
+static inline uint32_t bcmbal_ex_id_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bal_hdr_get(_msg_payload_ptr)->ex_id;
+}
+
+/*
+ * Set the ex_id field in the BAL header given the message pointer
+ */
+static inline void bcmbal_ex_id_set(void *_msg_payload_ptr, uint32_t _ex_id)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->ex_id = _ex_id;
+}
+
+/*
+ * Get the major version field in the BAL header given the message pointer
+ */
+static inline uint16_t bcmbal_major_version_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bal_hdr_get(_msg_payload_ptr)->version_major;
+}
+
+/*
+ * Set the major version field in the BAL header given the message pointer
+ */
+static inline void bcmbal_major_version_set(void *_msg_payload_ptr, uint16_t _version_major)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->version_major = _version_major;
+}
+
+/*
+ * Get the minor version field in the BAL header given the message pointer
+ */
+static inline uint16_t bcmbal_minor_version_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bal_hdr_get(_msg_payload_ptr)->version_minor;
+}
+
+/*
+ * Set the minor version field in the BAL header given the message pointer
+ */
+static inline void bcmbal_minor_version_set(void *_msg_payload_ptr, uint16_t _version_major)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->version_major = _version_major;
+}
+
+/*
+ * Get the scratchpad field in the BAL header given the message pointer
+ */
+static inline void *bcmbal_scratchpad_get(void *_msg_payload_ptr)
+{
+ return bcmbal_bal_hdr_get(_msg_payload_ptr)->scratchpad;
+}
+
+/*
+ * Set the scratchpad field in the BAL header given the message pointer
+ */
+static inline void bcmbal_scratchpad_set(void *_msg_payload_ptr, void *_scratchpad)
+{
+ bcmbal_bal_hdr_get(_msg_payload_ptr)->scratchpad = _scratchpad;
+}
+
+/*
+ * Allocate a BAL message given the payload pointer
+ */
+static inline void *bcmbal_msg_calloc(uint32_t _msg_payload_size)
+{
+ /* Payload includes comm header */
+ bal_comm_msg_hdr *m = bcmos_calloc(_msg_payload_size);
+ if (NULL == m)
+ return NULL;
+ return bcmbal_payload_ptr_get(m);
+}
+
+/*
+ * Free a BAL message given the payload pointer
+ */
+static inline void bcmbal_msg_free(void *msg)
+{
+ return bcmos_msg_free(bcmbal_bcmos_hdr_get(msg));
+}
+
+/*
+ * External functions implemented in bal_msg.c
+ */
+
+/*
+ * Clone BAL message
+ * Returns payload_ptr of the clone
+ */
+void *bcmbal_msg_clone(void *bal_obj);
+
+/*
+ * Send a BAL message given the payload pointer
+ */
+bcmos_errno bcmbal_msg_send(bcmos_msg_queue *queue, void *msg_payload, bcmos_msg_send_flags flags);
+
+/*
+ * Call callback in the context of the target module and pass it the BAL message pointer
+ */
+bcmos_errno bcmbal_msg_call(void *msg_payload, bcmos_module_id module, F_bcmos_msg_handler cb, bcmos_msg_send_flags flags);
+
+/*
+ * Receive a BAL message given the payload pointer
+ *
+ * NOTE: The timeout argument is in units of uS (micro seconds). Use the #defined timeout values above.
+ *
+ */
+bcmos_errno bcmbal_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, void **msg_payload);
+
+/** Get packed bal_comm_msg_hdr length */
+int32_t bcmbal_bal_msg_hdr_get_packed_length(void);
+
+/** Pack a BAL message header to a byte stream */
+bcmos_errno bcmbal_bal_msg_hdr_pack(const bal_comm_msg_hdr *msg, bcmbal_buf *buf);
+
+/** Unpack a BAL message header from a byte stream */
+bcmos_errno bcmbal_bal_msg_hdr_unpack(bal_comm_msg_hdr *msg, bcmbal_buf *buf);
+
+/** Peek exchange_id in the received message without unpacking */
+bcmos_errno bcmbal_bal_msg_peek_ex_id(bcmos_msg *msg, uint32_t *ex_id);
+
+#endif /* #ifndef BALMSG_H */
+
+
+
diff --git a/bal_release/src/common/include/bal_msg_type.h b/bal_release/src/common/include/bal_msg_type.h
new file mode 100644
index 0000000..38e98c6
--- /dev/null
+++ b/bal_release/src/common/include/bal_msg_type.h
@@ -0,0 +1,57 @@
+/******************************************************************************
+ *
+ * <: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 _BAL_MSG_TYPE_H_
+#define _BAL_MSG_TYPE_H_
+
+/*
+ * * The BAL message subtype
+ * */
+typedef enum
+{
+ BAL_MSG_TYPE_REQ,
+ BAL_MSG_TYPE_RSP,
+ BAL_MSG_TYPE_ACK,
+ BAL_MSG_TYPE_IND, /**< An INDication message generated as a part of a protocol exchange */
+ BAL_MSG_TYPE_AUTO_IND, /**< An asynchronous autonomous INDication message */
+} bcmbal_msg_type;
+
+static __attribute__ ((unused)) char *bcmbal_msg_t_str[] =
+{
+ "BAL_MSG_REQ",
+ "BAL_MSG_RSP",
+ "BAL_MSG_ACK",
+ "BAL_MSG_IND", /**< An INDication message generated as a part of a protocol exchange */
+ "BAL_MSG_AUTO_IND" /**< An asynchronous autonomous INDication message */
+};
+
+
+#endif
diff --git a/bal_release/src/common/include/bal_obj.h b/bal_release/src/common/include/bal_obj.h
new file mode 100644
index 0000000..24e8ec2
--- /dev/null
+++ b/bal_release/src/common/include/bal_obj.h
@@ -0,0 +1,205 @@
+#ifndef BAL_OBJ
+#define BAL_OBJ
+
+#include <bcmos_system.h>
+#include <bcmos_errno.h>
+#include "bal_model_ids.h"
+#include "bal_buf.h"
+#include "bal_msg_type.h"
+
+/*
+ * The current BAL header version
+ */
+#define BAL_HDR_VERSION_MAJOR (1)
+#define BAL_HDR_VERSION_MINOR (1)
+
+/*
+ * The BAL common message header
+ */
+typedef struct bal_comm_msg_hdr
+{
+ bcmos_msg m; /**< bcmos message header */
+ uint16_t version_major; /**< Header Major version number */
+ uint16_t version_minor; /**< Header Minor version number */
+ bcmbal_msg_type msg_type; /**< Request / Response / Ack / Indication */
+ uint32_t msg_id; /**< Message ID – the ID of the message (subID under the message type) */
+ uint32_t ex_id; /**< Exchange ID for message tracking between endpoints */
+ bal_subsystem sender; /**< Sender subsystem - used for additional validation */
+ uint32_t timestamp; /**< Timestamp when the message was sent */
+ bcmos_sem sem; /**< Semaphore used for inter-thread communication */
+ void* scratchpad; /**< Scratchpad used for inter-thread communication */
+ uint8_t payload[]; /**< Payload follows the header */
+} bal_comm_msg_hdr;
+
+/** Version of Object definitions */
+#define BCMBAL_OBJ_VERSION 2 /**< The current version number */
+typedef uint32_t bcmbal_object_ver; /**< The attribute type in the object info structure */
+
+/** Bitmask of object attributes that are specified in an object (1 = specified, 0 = not specified) */
+typedef uint64_t bcmbal_presence_mask;
+
+/** Presence mask indicating all fields present */
+#define BCMBAL_PRESENCE_MASK_ALL ((bcmbal_presence_mask)0xFFFFFFFFFFFFFFFF)
+
+/** Helper type to determine what the data format of a message should look like */
+typedef enum bcmbal_mgt_group
+{
+ BCMBAL_MGT_GROUP_KEY, /**< Key that uniquely identifies object instance */
+ BCMBAL_MGT_GROUP_CFG, /**< Configuration (get/set/clear) */
+ BCMBAL_MGT_GROUP_STAT, /**< Statistics */
+ BCMBAL_MGT_GROUP_AUTO, /**< Autonomous indications */
+ BCMBAL_MGT_GROUP_AUTO_CFG, /**< Autonomous indication configuration */
+ BCMBAL_MGT_GROUP__NUM_OF
+} bcmbal_mgt_group;
+
+/** Object message type. Can be a combination of flags. */
+typedef enum bcmbal_obj_msg_type
+{
+ BCMBAL_OBJ_MSG_TYPE_GET = 0x01, /**< Get configuration parameters */
+ BCMBAL_OBJ_MSG_TYPE_SET = 0x02, /**< Set configuration parameters */
+ BCMBAL_OBJ_MSG_TYPE_CLEAR = 0x04, /**< Clear configuration parameters */
+} bcmbal_obj_msg_type;
+
+/** Object message direction - request or response. */
+typedef enum bcmbal_obj_msg_dir
+{
+ BCMBAL_OBJ_MSG_DIR_REQUEST,
+ BCMBAL_OBJ_MSG_DIR_RESPONSE
+} bcmbal_obj_msg_dir;
+
+#define BCMBAL_OBJ_INIT_VAL 0xdeadbeef /**< The value of the obj_init_val after macro initialization */
+
+/** Information common to all BAL objects */
+typedef struct bcmbal_obj
+{
+ bal_comm_msg_hdr comm_hdr; /**< Communication header */
+ bcmbal_object_ver version; /**< Version of the Object definition/structure */
+ bcmbal_obj_id obj_type; /**< An enumerated ID associated with the object being specified */
+ bcmbal_mgt_group group; /**< Management group */
+ uint16_t subgroup; /**< Subgroup for indications */
+ bcmbal_obj_msg_type type; /**< Type (e.g. get / set / clear) */
+ bcmbal_obj_msg_dir dir; /**< Direction - request / response */
+ bcmos_errno status; /**< BAL status code (BCM_ERR_OK–success, error code otherwise) */
+ bcmbal_presence_mask presence_mask; /**< Indicates which attribute parameters are present */
+
+ /* The following fields are internal. They are not sent on the line */
+ bcmos_bool is_inprogress; /**< RO - When set to TRUE: Object is changing state internally */
+ void *list_buf; /**< Memory buffer in which to store variable-sized lists when unpacking */
+ uint32_t list_buf_size; /**< Number of bytes in the variable-sized list buffer */
+ uint32_t obj_init_val; /**< An field that is set on INIT macro call, and checked by the API */
+} bcmbal_obj;
+
+/** Information structure for use with BAL configuration API (get/set/clear) */
+typedef struct bcmbal_cfg
+{
+ bcmbal_obj hdr;
+} bcmbal_cfg;
+
+/** Information structure for BAL statistics API */
+typedef struct bcmbal_stat
+{
+ bcmbal_obj hdr;
+} bcmbal_stat;
+
+/** Information structure for BAL indications */
+typedef struct bcmbal_auto
+{
+ bcmbal_obj hdr;
+} bcmbal_auto;
+
+/** Information structure for BAL indication configuration API */
+typedef struct bcmbal_auto_cfg
+{
+ bcmbal_obj hdr;
+} bcmbal_auto_cfg;
+
+/** Whether we pack the entire structure of a message */
+static inline bcmos_bool bcmbal_obj_msg_should_pack_data(const bcmbal_obj *msg)
+{
+ switch (msg->group)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ case BCMBAL_MGT_GROUP_STAT:
+ case BCMBAL_MGT_GROUP_AUTO_CFG:
+ if ((msg->type & BCMBAL_OBJ_MSG_TYPE_GET))
+ {
+ return (msg->dir == BCMBAL_OBJ_MSG_DIR_RESPONSE);
+ }
+ else if ((msg->type & BCMBAL_OBJ_MSG_TYPE_SET))
+ {
+ return (msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST);
+ }
+ else
+ {
+ return BCMOS_FALSE;
+ }
+
+ default:
+ return BCMOS_TRUE;
+ }
+}
+
+/** Get the packed length of the header portion of an object message */
+static inline int32_t bcmbal_obj_msg_hdr_get_packed_length(void)
+{
+ return 24;
+}
+
+/** Pack a message header to a byte stream */
+static inline bcmos_errno bcmbal_obj_msg_hdr_pack(const bcmbal_obj *msg, bcmbal_buf *buf)
+{
+ bcmos_bool ret;
+
+ ret = bcmbal_buf_write_u32(buf, (uint32_t)msg->version);
+ ret = ret && bcmbal_buf_write_u8(buf, (uint32_t)msg->obj_type);
+ ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->group);
+ ret = ret && bcmbal_buf_write_u16(buf, msg->subgroup);
+ ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->type);
+ ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->dir);
+ ret = ret && bcmbal_buf_write_s16(buf, (int16_t)msg->status);
+ ret = ret && bcmbal_buf_write_u32(buf, (int32_t)msg->is_inprogress);
+ ret = ret && bcmbal_buf_write_u64(buf, (uint64_t)msg->presence_mask);
+
+ return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
+}
+
+/** Unpack a message header from a byte stream */
+static inline bcmos_errno bcmbal_obj_msg_hdr_unpack(bcmbal_obj *msg, bcmbal_buf *buf)
+{
+ uint32_t version;
+ uint8_t obj_type;
+ uint8_t group;
+ uint16_t subgroup;
+ uint8_t type;
+ uint8_t dir;
+ int16_t status;
+ uint32_t is_inprogress;
+ uint64_t presence_mask;
+ bcmos_bool ret;
+
+ ret = bcmbal_buf_read_u32(buf, &version);
+ ret = ret && bcmbal_buf_read_u8(buf, &obj_type);
+ ret = ret && bcmbal_buf_read_u8(buf, &group);
+ ret = ret && bcmbal_buf_read_u16(buf, &subgroup);
+ ret = ret && bcmbal_buf_read_u8(buf, &type);
+ ret = ret && bcmbal_buf_read_u8(buf, &dir);
+ ret = ret && bcmbal_buf_read_s16(buf, &status);
+ ret = ret && bcmbal_buf_read_u32(buf, &is_inprogress);
+ ret = ret && bcmbal_buf_read_u64(buf, &presence_mask);
+ if (ret)
+ {
+ msg->version = (bcmbal_object_ver)version;
+ msg->obj_type = (bcmbal_obj_id)obj_type;
+ msg->group = (bcmbal_mgt_group)group;
+ msg->subgroup = subgroup;
+ msg->type = (bcmbal_obj_msg_type)type;
+ msg->dir = (bcmbal_obj_msg_dir)dir;
+ msg->status = (bcmos_errno)status;
+ msg->is_inprogress = (bcmos_bool)is_inprogress;
+ msg->presence_mask = (bcmbal_presence_mask)presence_mask;
+ }
+
+ return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
+}
+
+#endif /* BAL_OBJ */
diff --git a/bal_release/src/common/include/bal_objs.h b/bal_release/src/common/include/bal_objs.h
new file mode 100644
index 0000000..6a13cce
--- /dev/null
+++ b/bal_release/src/common/include/bal_objs.h
@@ -0,0 +1,985 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_objs.h
+ * @brief The file provides an enumeration of all BAL objects
+ *
+ */
+#ifndef BALOBJS_H
+#define BALOBJS_H
+
+#include <bcmolt_host_api.h>
+#include "bal_common.h"
+#include "bal_model_ids.h"
+#include "bal_model_types.h"
+
+/** \ingroup api
+ * @{
+ */
+
+static char *bal_obj_str[] =
+{
+ [bcmbal_obj_id_access_terminal] = "access_terminal object",
+ [bcmbal_obj_id_interface] = "interface object",
+ [bcmbal_obj_id_subscriber_terminal] = "subscriber_terminal object",
+ [bcmbal_obj_id_flow] = "flow object",
+ [bcmbal_obj_id_packet] = "packet object",
+ [bcmbal_obj_id_group] = "group object",
+ [bcmbal_obj_id_tm_sched] = "scheduler object",
+ [bcmbal_obj_id_tm_queue] = "queue object",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (BCMBAL_OBJ_ID__NUM_OF == (sizeof (bal_obj_str) / sizeof (char *)), bcmbal_obj_id);
+
+static inline char *bcmbal_objtype_str(bcmbal_obj_id obj)
+{
+ return (BCMBAL_OBJ_ID__NUM_OF >= obj) ? bal_obj_str[obj] : "unknown";
+}
+
+#define BCMBAL_FLOW_PRIORITY_MAX 65535
+#define BCMBAL_FLOW_PRIORITY_MIN 0
+#define BAL_FLOW_DEFAULT_PRIORITY 10
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * Internal BCMBAL macros used to manipulate the BAL object elements
+ *
+ * ------------------------------------------------------------------
+ */
+
+/* Initialize request. Internal macro
+ * \ingroup api
+ * \param[in] _h Message header
+ * \param[in] _obj Object name (i.e. flow)
+ * \param[in] _grp message type
+ * \param[in] _subgrp message subgroup
+ */
+#define _BCMBAL_REQ_INIT(_h, _obj, _grp, _subgrp) \
+ (_h)->obj_init_val = BCMBAL_OBJ_INIT_VAL; \
+ (_h)->version = BCMBAL_OBJ_VERSION; \
+ (_h)->status = BCM_ERR_OK; \
+ (_h)->presence_mask = 0; \
+ (_h)->obj_type = bcmbal_obj_id_ ## _obj; \
+ (_h)->group = _grp; \
+ (_h)->subgroup = _subgrp;
+
+/** Initialize set structure
+ * \ingroup api
+ * \param[in] _s Set structure
+ * \param[in] _obj Object name (i.e. flow)
+ * \param[in] _key Object key
+ */
+#define BCMBAL_CFG_INIT(_s, _obj, _key) \
+ do { \
+ bcmbal_ ## _obj ## _cfg *_x_ = _s; \
+ memset(_x_, 0, sizeof(*_x_)); \
+ _BCMBAL_REQ_INIT(&((_x_)->hdr.hdr), _obj, BCMBAL_MGT_GROUP_CFG, 0); \
+ (_x_)->key = _key; \
+ } while (0)
+
+/** Initialize statistics structure
+ * \ingroup api
+ * \param[in] _s Statistics structure
+ * \param[in] _obj Object name (i.e. flow)
+ * \param[in] _key Object key
+ */
+#define BCMBAL_STAT_INIT(_s, _obj, _key) \
+ do { \
+ bcmbal_ ## _obj ## _stat *_x_ = _s; \
+ memset(_x_, 0, sizeof(*_x_)); \
+ _BCMBAL_REQ_INIT(&((_x_)->hdr.hdr), _obj, BCMBAL_MGT_GROUP_STAT, 0); \
+ (_x_)->key = _key; \
+ } while (0)
+
+/** Set the memory buffer to use for variable-sized lists within a cfg get
+ * \ingroup api
+ * \param[in] _s Configuration structure
+ * \param[in] _obj Object type
+ * \param[in] _buf Pointer to a location in memory in which to store the lists
+ * \param[in] _len Length of the buffer pointed to by _buf
+ */
+#define BCMBAL_CFG_LIST_BUF_SET(_s, _obj, _buf, _len) \
+ do { \
+ bcmbal_ ## _obj ## _cfg *_x_ = _s; \
+ _x_->hdr.hdr.list_buf = _buf; \
+ _x_->hdr.hdr.list_buf_size = _len; \
+ } while (0)
+
+/* Set the object progress state
+ * \ingroup api
+ * \param[in] _s Object structure
+ * \param[in] _p New object in-progress state: BCMOS_TRUE, or BCMOS_FALSE
+ */
+#define BCMBAL_OBJ_IN_PROGRESS_SET(_s, _p) ((_s)->hdr.hdr.is_inprogress = _p )
+
+/* Return the object progress state
+ * \ingroup api
+ * \param[in] _s Object structure
+ */
+#define BCMBAL_OBJ_IN_PROGRESS_GET(_s) ((_s)->hdr.hdr.is_inprogress)
+
+/* Internal macro: Get a bitmask given a property ID enum */
+#define BCMBAL_PROP_MASK_GET(_obj, _grp, _p) \
+ (bcmbal_ ## _obj ## _grp ## _id_ ## _p == bcmbal_ ## _obj ## _grp ## _id_all_properties ? \
+ ((1ULL << (uint64_t)bcmbal_ ## _obj ## _grp ## _id_ ## _p) - 1) : \
+ (1ULL << (uint64_t)bcmbal_ ## _obj ## _grp ## _id_ ## _p))
+
+
+/* Macro: Indicate that configuration property is present - USE WITH CAUTION */
+#define BCMBAL_PROP_SET_PRESENT(_m, _obj, _grp, _p) \
+ do { \
+ (_m)->hdr.hdr.presence_mask |= BCMBAL_PROP_MASK_GET(_obj, _grp, _p); \
+ } while (0)
+
+/* Internal macro: Indicate that configuration property is not present */
+#define BCMBAL_PROP_CLEAR_PRESENT(_m, _obj, _grp, _p) \
+ do { \
+ (_m)->hdr.hdr.presence_mask &= ~(BCMBAL_PROP_MASK_GET(_obj, _grp, _p));\
+ } while (0)
+
+/* Internal macro: check if property is present */
+#define _BCMBAL_PROP_IS_PRESENT(_m, _obj, _grp, _p) \
+ (((_m)->hdr.hdr.presence_mask & BCMBAL_PROP_MASK_GET(_obj, _grp, _p)) ? \
+ BCMOS_TRUE : BCMOS_FALSE)
+
+/** Set configuration property in message structure
+ * \ingroup api
+ * \param[in] _m Configuration structure
+ * \param[in] _obj Object type
+ * \param[in] _p Property name
+ * \param[in] _v Property value
+ */
+#define BCMBAL_CFG_PROP_SET(_m, _obj, _p, _v) \
+ do { \
+ BCMBAL_PROP_SET_PRESENT(_m, _obj, _cfg, _p);\
+ (_m)->data._p = (_v);\
+ } while (0)
+
+/** Indicate that configuration property should be read
+ * \ingroup api
+ * \param[in] _m Configuration structure
+ * \param[in] _obj Object type
+ * \param[in] _p Property name
+ */
+#define BCMBAL_CFG_PROP_GET(_m, _obj, _p) BCMBAL_PROP_SET_PRESENT(_m, _obj, _cfg, _p)
+
+/** clear object property in message structure
+ * \ingroup api
+ * \param[in] _m Object structure pointer
+ * \param[in] _obj Object name (i.e. flow)
+ * \param[in] _p Attribute name (i.e. admin_state)
+ */
+#define BCMBAL_CFG_PROP_CLEAR(_m, _obj, _p) \
+ do { \
+ BCMBAL_PROP_CLEAR_PRESENT(_m, _obj, _cfg, _p); \
+ memset(&((_m)->data._p), 0, sizeof((_m)->data._p)); \
+ } while (0)
+
+/** Check if configuration property is set in message structure
+ * \ingroup api
+ * \param[in] _m Configuration structure
+ * \param[in] _obj Object type
+ * \param[in] _p Property name
+ */
+#define BCMBAL_CFG_PROP_IS_SET(_m, _obj, _p) _BCMBAL_PROP_IS_PRESENT(_m, _obj, _cfg, _p)
+
+/** Indicate that statistic property should be read
+ * \ingroup api
+ * \param[in] _m Configuration structure
+ * \param[in] _obj Object type
+ * \param[in] _p Property name
+ */
+#define BCMBAL_STAT_PROP_GET(_m, _obj, _p) BCMBAL_PROP_SET_PRESENT(_m, _obj, _stat, _p)
+
+/** Check if statistic property is set in message structure
+ * \ingroup api
+ * \param[in] _m Statistic structure
+ * \param[in] _obj Object type
+ * \param[in] _p Property name
+ */
+#define BCMBAL_STAT_PROP_IS_SET(_m, _obj, _p) _BCMBAL_PROP_IS_PRESENT(_m, _obj, _stat, _p)
+
+
+/***********************************************************************************
+ **
+ ** Macros for setting attribute values where an attribute supports a presence_mask
+ **
+ ***********************************************************************************
+ **/
+
+/* Internal macro: Get a bitmask given a attribute element property ID enum */
+#define BCMBAL_ATTRIBUTE_PROP_MASK_GET(_attr, _p) bcmbal_ ## _attr ## _id_ ## _p
+
+/* Internal macro: Indicate that configuration property is present */
+#define _BCMBAL_ATTRIBUTE_PROP_SET_PRESENT(p_attr, _attr,_p) \
+ do { \
+ (p_attr)->presence_mask |= BCMBAL_ATTRIBUTE_PROP_MASK_GET(_attr, _p); \
+ } while (0)
+
+/* Internal macro: Indicate that configuration property is not present */
+#define _BCMBAL_ATTRIBUTE_PROP_CLEAR_PRESENT(p_attr, _attr,_p) \
+ do { \
+ (p_attr)->presence_mask &= ~(BCMBAL_ATTRIBUTE_PROP_MASK_GET(_attr, _p)); \
+ } while (0)
+
+/** Set attribute element property in message structure
+ * \param[in] _p_attr Attribute structure pointer
+ * \param[in] _attr Attribute name
+ * \param[in] _p Element name (i.e. o_tpid)
+ * \param[in] _v Element value
+ */
+#define BCMBAL_ATTRIBUTE_PROP_SET(_p_attr, _attr, _p, _v) \
+ do { \
+ _BCMBAL_ATTRIBUTE_PROP_SET_PRESENT(_p_attr, _attr, _p); \
+ (_p_attr)->_p = (_v); \
+ } while (0)
+
+/** Clear attribute element property in message structure
+ * \param[in] _p_attr Attribute structure pointer
+ * \param[in] _attr Attribute name
+ * \param[in] _p Element name (i.e. o_tpid)
+ */
+#define BCMBAL_ATTRIBUTE_PROP_CLEAR(_p_attr, _attr, _p) \
+ do { \
+ _BCMBAL_ATTRIBUTE_PROP_CLEAR_PRESENT(_p_attr, _attr, _p); \
+ memset(&((_p_attr)->_p), 0, sizeof((_p_attr)->_p)); \
+ } while (0)
+
+
+/* Internal macro: check if an attribute element is present */
+#define _BCMBAL_ATTRIBUTE_PROP_IS_PRESENT(_p_attr, _attr, _p) \
+ (((_p_attr)->presence_mask & BCMBAL_ATTRIBUTE_PROP_MASK_GET(_attr, _p)) ? \
+ BCMOS_TRUE : BCMOS_FALSE)
+
+/** Check if attribute element property is set in message structure
+ * \param[in] _p_attr Attribute structure pointer
+ * \param[in] _attr Attribute name
+ * \param[in] _p Element name (i.e. o_tpid)
+ */
+#define BCMBAL_ATTRIBUTE_PROP_IS_SET(_p_attr, _attr, _p) _BCMBAL_ATTRIBUTE_PROP_IS_PRESENT(_p_attr, _attr, _p)
+
+
+/*
+ * ------------------------------------------------------------------
+ *
+ * Internal BCMBAL macros used to manipulate cmds_bitmask of action parameters
+ *
+ * ------------------------------------------------------------------
+ */
+
+/** Check if action cmd id is set in action structure
+ * \param[in] _m Object structure pointer
+ * \param[in] _b cmd Id bitmask
+ */
+#define BCMBAL_ACTION_CMD_ID_IS_SET(_m, _b) \
+ (((_m)->cmds_bitmask & (_b)) ? \
+ BCMOS_TRUE : BCMOS_FALSE)
+
+/** Set action cmd id in action structure
+ * \param[in] _m Object structure pointer
+ * \param[in] _b cmd Id bitmask
+ */
+#define BCMBAL_ACTION_CMD_ID_SET(_m, _b) \
+ do { \
+ (_m)->cmds_bitmask |= (_b);\
+ } while (0)
+
+
+/** Clear action cmd id in action structure
+ * \param[in] _m Object structure pointer
+ * \param[in] _b cmd Id bitmask
+ */
+#define BCMBAL_ACTION_CMD_ID_CLEAR(_m, _b) \
+ do { \
+ (_m)->cmds_bitmask &= ~(_b);\
+ } while (0)
+
+
+
+static inline void bcmbal_flow_object_overlay_w_src_priority(bcmbal_flow_cfg *dstobj, bcmbal_flow_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, admin_state))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, admin_state, srcobj->data.admin_state);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, access_int_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, access_int_id, srcobj->data.access_int_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, network_int_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, network_int_id, srcobj->data.network_int_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, sub_term_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, sub_term_id, srcobj->data.sub_term_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, svc_port_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, svc_port_id, srcobj->data.svc_port_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, agg_port_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, agg_port_id, srcobj->data.agg_port_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, resolve_mac))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, resolve_mac, srcobj->data.resolve_mac);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, queue))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, queue, srcobj->data.queue);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, action))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, action, srcobj->data.action);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, classifier))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, classifier, srcobj->data.classifier);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, sla))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, sla, srcobj->data.sla);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, group_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, group_id, srcobj->data.group_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, cookie))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, flow, cookie, srcobj->data.cookie);
+ }
+}
+
+static inline void bcmbal_flow_object_overlay_w_dst_priority(bcmbal_flow_cfg *dstobj, bcmbal_flow_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety,
+ * except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source and are not already set in the dst object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, admin_state))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, admin_state))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, admin_state, srcobj->data.admin_state);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, access_int_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, access_int_id))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, access_int_id, srcobj->data.access_int_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, network_int_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, network_int_id))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, network_int_id, srcobj->data.network_int_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, sub_term_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, sub_term_id))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, sub_term_id, srcobj->data.sub_term_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, svc_port_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, svc_port_id))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, svc_port_id, srcobj->data.svc_port_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, agg_port_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, agg_port_id))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, agg_port_id, srcobj->data.agg_port_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, resolve_mac))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, resolve_mac))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, resolve_mac, srcobj->data.resolve_mac);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, queue))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, queue))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, queue, srcobj->data.queue);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, action))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, action))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, action, srcobj->data.action);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, classifier))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, classifier))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, classifier, srcobj->data.classifier);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, sla))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, sla))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, sla, srcobj->data.sla);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, group_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, group_id))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, group_id, srcobj->data.group_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, flow, cookie))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, flow, cookie))
+ BCMBAL_CFG_PROP_SET(dstobj, flow, cookie, srcobj->data.cookie);
+ }
+}
+
+static inline void bcmbal_sub_term_object_overlay_w_src_priority(bcmbal_subscriber_terminal_cfg *dstobj,
+ bcmbal_subscriber_terminal_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, admin_state))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, admin_state, srcobj->data.admin_state);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, serial_number))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, serial_number, srcobj->data.serial_number);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, password))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, password, srcobj->data.password);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, registration_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, registration_id, srcobj->data.registration_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, svc_port_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, svc_port_id, srcobj->data.svc_port_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, ds_tm))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, ds_tm, srcobj->data.ds_tm);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, us_tm))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, us_tm, srcobj->data.us_tm);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, mac_address))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, mac_address, srcobj->data.mac_address);
+ }
+}
+
+static inline void bcmbal_sub_term_object_overlay_w_dst_priority(bcmbal_subscriber_terminal_cfg *dstobj,
+ bcmbal_subscriber_terminal_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, admin_state))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, admin_state))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, admin_state, srcobj->data.admin_state);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, serial_number))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, serial_number))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, serial_number, srcobj->data.serial_number);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, password))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, password))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, password, srcobj->data.password);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, registration_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, registration_id))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, registration_id, srcobj->data.registration_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, svc_port_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, svc_port_id))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, svc_port_id, srcobj->data.svc_port_id);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, ds_tm))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, ds_tm))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, ds_tm, srcobj->data.ds_tm);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, us_tm))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, us_tm))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, us_tm, srcobj->data.us_tm);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, subscriber_terminal, mac_address))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, subscriber_terminal, mac_address))
+ BCMBAL_CFG_PROP_SET(dstobj, subscriber_terminal, mac_address, srcobj->data.mac_address);
+ }
+}
+
+static inline void bcmbal_tm_sched_object_overlay_w_src_priority(bcmbal_tm_sched_cfg *dstobj, bcmbal_tm_sched_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, owner))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, owner, srcobj->data.owner);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, sched_type))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, sched_type, srcobj->data.sched_type);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, sched_parent))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, sched_parent, srcobj->data.sched_parent);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, sched_child_type))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, sched_child_type, srcobj->data.sched_child_type);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, rate))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, rate, srcobj->data.rate);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, tcont_sla))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, tcont_sla, srcobj->data.tcont_sla);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, creation_mode))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, creation_mode, srcobj->data.creation_mode);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, num_priorities))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, num_priorities, srcobj->data.num_priorities);
+ }
+
+}
+
+
+
+static inline void bcmbal_tm_sched_object_overlay_w_dst_priority(bcmbal_tm_sched_cfg *dstobj, bcmbal_tm_sched_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety,
+ * except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source and are not already set in the dst object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, owner))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, owner))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, owner, srcobj->data.owner);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, sched_type))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, sched_type))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, sched_type, srcobj->data.sched_type);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, sched_parent))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, sched_parent))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, sched_parent, srcobj->data.sched_parent);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, sched_child_type))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, sched_child_type))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, sched_child_type, srcobj->data.sched_child_type);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, rate))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, rate))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, rate, srcobj->data.rate);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, tcont_sla))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, tcont_sla))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, tcont_sla, srcobj->data.tcont_sla);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_sched, creation_mode))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, tm_sched, creation_mode))
+ BCMBAL_CFG_PROP_SET(dstobj, tm_sched, creation_mode, srcobj->data.creation_mode);
+ }
+
+}
+
+
+static inline void bcmbal_tm_queue_object_overlay(bcmbal_tm_queue_cfg *dstobj, bcmbal_tm_queue_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source object */
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_queue, priority))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_queue, priority, srcobj->data.priority);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_queue, weight))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_queue, weight, srcobj->data.weight);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_queue, rate))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_queue, rate, srcobj->data.rate);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, tm_queue, bac))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, tm_queue, bac, srcobj->data.bac);
+ }
+}
+
+static inline bcmos_errno bal_obj_key_str_get(bcmbal_obj *obj, char *p_obj_key_str)
+{
+ BUG_ON(NULL == p_obj_key_str);
+
+ bcmos_errno ret = BCM_ERR_OK;
+
+ switch (obj->obj_type)
+ {
+
+ case (BCMBAL_OBJ_ID_ACCESS_TERMINAL):
+ {
+ sprintf(p_obj_key_str, "unit:%d",
+ ((bcmbal_access_terminal_cfg *)obj)->key.access_term_id);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_INTERFACE):
+ {
+ sprintf(p_obj_key_str, "intf_id:%d, type:%s",
+ ((bcmbal_interface_cfg *)obj)->key.intf_id,
+ ((bcmbal_interface_cfg *)obj)->key.intf_type == BCMBAL_INTF_TYPE_NNI ? "NNI" :
+ ((bcmbal_interface_cfg *)obj)->key.intf_type == BCMBAL_INTF_TYPE_PON ? "PON" :
+ "???"
+ );
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL):
+ {
+ sprintf(p_obj_key_str, "sub_term_id:%d, intf_id:%d",
+ ((bcmbal_subscriber_terminal_cfg *)obj)->key.sub_term_id,
+ ((bcmbal_subscriber_terminal_cfg *)obj)->key.intf_id);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_FLOW):
+ {
+ sprintf(p_obj_key_str, "flow_id:%d, type:%s",
+ ((bcmbal_flow_cfg *)obj)->key.flow_id,
+ ((bcmbal_flow_cfg *)obj)->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ? "upstream" :
+ ((bcmbal_flow_cfg *)obj)->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM ? "downstream" :
+ ((bcmbal_flow_cfg *)obj)->key.flow_type == BCMBAL_FLOW_TYPE_BROADCAST ? "broadcast" :
+ ((bcmbal_flow_cfg *)obj)->key.flow_type == BCMBAL_FLOW_TYPE_MULTICAST ? "multicast" :
+ "???"
+ );
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_GROUP):
+ {
+ sprintf(p_obj_key_str, "group_id:%d",
+ ((bcmbal_group_cfg *)obj)->key.group_id);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_TM_SCHED):
+ {
+ sprintf(p_obj_key_str, "dir:%s, id:%d",
+ ((bcmbal_tm_sched_cfg *)obj)->key.dir == BCMBAL_TM_SCHED_DIR_US ? "upstream" :
+ ((bcmbal_tm_sched_cfg *)obj)->key.dir == BCMBAL_TM_SCHED_DIR_DS ? "downstream" :
+ "???",
+ ((bcmbal_tm_sched_cfg *)obj)->key.id
+ );
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_TM_QUEUE):
+ {
+ sprintf(p_obj_key_str, "sched_id:%d, sched_dir:%s, id:%d",
+ ((bcmbal_tm_queue_cfg *)obj)->key.sched_id,
+ ((bcmbal_tm_queue_cfg *)obj)->key.sched_dir == BCMBAL_TM_SCHED_DIR_US ? "upstream" :
+ ((bcmbal_tm_queue_cfg *)obj)->key.sched_dir == BCMBAL_TM_SCHED_DIR_DS ? "downstream" :
+ "???",
+ ((bcmbal_tm_queue_cfg *)obj)->key.id
+ );
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_PACKET):
+ {
+ sprintf(p_obj_key_str, " ");
+ break;
+ }
+
+ default:
+ sprintf(p_obj_key_str, " ");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ return ret;
+}
+
+static inline void bcmbal_interface_object_overlay_w_dst_priority(bcmbal_interface_cfg *dstobj, bcmbal_interface_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety,
+ * except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source and are not already set in the dst object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, admin_state))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, admin_state))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, admin_state, srcobj->data.admin_state);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, min_data_agg_port_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, min_data_agg_port_id))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, min_data_agg_port_id, srcobj->data.min_data_agg_port_id);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, min_data_svc_port_id))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, min_data_svc_port_id))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, min_data_svc_port_id, srcobj->data.min_data_svc_port_id);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, transceiver_type))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, transceiver_type))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, transceiver_type, srcobj->data.transceiver_type);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, ds_miss_mode))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, ds_miss_mode))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, ds_miss_mode, srcobj->data.ds_miss_mode);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, mtu))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, mtu))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, mtu, srcobj->data.mtu);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, flow_control))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, flow_control))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, flow_control, srcobj->data.flow_control);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, ds_tm))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, ds_tm))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, ds_tm, srcobj->data.ds_tm);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, us_tm))
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(dstobj, interface, us_tm))
+ BCMBAL_CFG_PROP_SET(dstobj, interface, us_tm, srcobj->data.us_tm);
+ }
+}
+
+
+static inline void bcmbal_interface_object_overlay_w_src_priority(bcmbal_interface_cfg *dstobj,
+ bcmbal_interface_cfg *srcobj)
+{
+ BUG_ON(NULL == dstobj);
+ BUG_ON(NULL == srcobj);
+
+ bcmbal_presence_mask dest_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ dest_presence_mask = dstobj->hdr.hdr.presence_mask;
+ dstobj->hdr = srcobj->hdr;
+ dstobj->key = srcobj->key;
+ dstobj->hdr.hdr.presence_mask = dest_presence_mask;
+
+ /* Now copy only the fields that have been specified in the source object */
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, admin_state))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, admin_state, srcobj->data.admin_state);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, min_data_agg_port_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, min_data_agg_port_id, srcobj->data.min_data_agg_port_id);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, min_data_svc_port_id))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, min_data_svc_port_id, srcobj->data.min_data_svc_port_id);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, transceiver_type))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, transceiver_type, srcobj->data.transceiver_type);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, ds_miss_mode))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, ds_miss_mode, srcobj->data.ds_miss_mode);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, mtu))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, mtu, srcobj->data.mtu);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, flow_control))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, flow_control, srcobj->data.flow_control);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, ds_tm))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, ds_tm, srcobj->data.ds_tm);
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(srcobj, interface, us_tm))
+ {
+ BCMBAL_CFG_PROP_SET(dstobj, interface, us_tm, srcobj->data.us_tm);
+ }
+
+}
+/*@}*/
+
+
+#endif /* BALOBJS_H */
diff --git a/bal_release/src/common/include/bal_osmsg.h b/bal_release/src/common/include/bal_osmsg.h
new file mode 100644
index 0000000..e5caf85
--- /dev/null
+++ b/bal_release/src/common/include/bal_osmsg.h
@@ -0,0 +1,104 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_osmsg.h
+ * @brief BAL Message data structure definitions
+ *
+ */
+#ifndef BAL_OSMSG_H_
+#define BAL_OSMSG_H_
+/*
+ * Message structures.
+ * Going to be generated from object model and moved elsewhere
+ */
+
+/* BAL subsystem */
+typedef enum
+{
+ BAL_SUBSYSTEM_CORE,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BAL_SUBSYSTEM_SWITCH_UTIL,
+ BAL_SUBSYSTEM_PUBLIC_API,
+
+ BAL_SUBSYSTEM__NUM_OF
+} bal_subsystem;
+
+
+__attribute__ ((unused)) static const char *subsystem_str[] =
+{
+ "BAL Core",
+ "BAL Mac Util",
+ "BAL Switch Util",
+ "BAL Public API"
+};
+
+/** BAL OS message
+ * \ingroup system_msg
+ */
+typedef enum
+{
+ BCMOS_MSG_ID__BEGIN,
+
+ /* Messages used internally by OS abstraction. Do not touch */
+ BCMOS_MSG_ID_INTERNAL_TIMER, /**< Internal "timer message" type */
+ BCMOS_MSG_ID_INTERNAL_EVENT, /**< Internal "event message" type */
+ BCMOS_MSG_ID_INTERNAL_IPC,
+
+ /* Application messages */
+ BCMOS_MSG_ID_IPC_PING, /*** Inter-process communication ping */
+
+ /* Core/Switch util messages */
+ BCMBAL_SWITCH_UTIL_MSG,
+
+ /* Core/Mac util messages */
+ BCMBAL_MAC_UTIL_MSG,
+
+ /* Core<->Public API messages */
+ BCMBAL_MGMT_MSG,
+
+ /* Core->Public API indication messages (both auto and "normal") */
+ BCMBAL_MGMT_API_IND_MSG,
+
+ BCMOS_MSG_ID_EON_PROXY_RX,
+ BCMOS_MSG_ID_EON_DESTROY_STATE,
+
+ BCMOS_MSG_ID_EPON_OAM_PROXY_RX,
+ BCMOS_MSG_ID_EPON_OAM_TIMEOUT,
+
+ BCMOS_MSG_ID_OMCI_TRANSPORT_SEND,
+
+ BCMOS_MSG_ID__END,
+ BCMOS_MSG_ID__FORCE16 = 0x7fff
+} bcmos_msg_id;
+
+
+#endif /* BAL_OSMSG_H_ */
diff --git a/bal_release/src/common/include/bal_utils_msg.h b/bal_release/src/common/include/bal_utils_msg.h
new file mode 100644
index 0000000..d6721fc
--- /dev/null
+++ b/bal_release/src/common/include/bal_utils_msg.h
@@ -0,0 +1,180 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/******************************************************************************
+The message format will look like the following
+
+ -----------------------------------------------------------------------------------
+ | BAL Header | | Payload Data |
+ ----------------------------------|------------------------------------------------
+ | *bcmos_header | | App Header | |
+ -----------------------------------------------------------------------------------
+ | | | version | |
+ | type | msg_type | obj_key | bal_util_ind_flow_t |
+ | | msg_id | status | |
+ -----------------------------------------------------------------------------------
+
+ *The bcmos Header is actually the first field of BAL Header structure (bal_comm_msg_hdr_t)
+
+ type can be:
+ BCMBAL_SWITCH_UTIL_MSG
+ BCMBAL_MAC_UTIL_MSG
+
+ msg_type can be:
+ BAL_MSG_IND,
+ BAL_MSG_AUTO_IND
+
+ msg_id is module specific, but contains two 16 bits fields (OBJECT_ID, OPERATION_ID)
+ see bal_objs.h for OBJECT_ID details
+ The OPERATION_ID should be unique within the OBJECT - see example below
+ bal_msg.h
+
+ status is for indication message to show general results. The value is bcmos_errno.
+
+*********************************************************************************/
+
+/**
+ * @file bal_utils_msg.h
+ *
+ * @brief Common header for messages sent between Utils and Core
+ *
+ * @ingroup apps
+ */
+
+#ifndef _BAL_UTIL_MSG_H_
+#define _BAL_UTIL_MSG_H_
+
+/*@{*/
+
+#include <bal_msg.h>
+#include <stdint.h>
+
+#define BAL_UTIL_MSG_VERSION 1
+
+/* access terminal request list,
+ */
+typedef enum
+{
+ BAL_UTIL_OPER_ACC_TERM_CONNECT,
+ BAL_UTIL_OPER_ACC_TERM_DISCONNECT
+} bal_util_oper_acc_term;
+
+/* subscriber terminal request list,
+ */
+typedef enum
+{
+ BAL_UTIL_OPER_SUB_TERM_ADD,
+ BAL_UTIL_OPER_SUB_TERM_REMOVE,
+ BAL_UTIL_OPER_SUB_TERM_CLEAR,
+ BAL_UTIL_OPER_SUB_TERM_DISCOVERY
+} bal_util_oper_sub_term;
+
+/* interface request list,
+ */
+typedef enum
+{
+ BAL_UTIL_OPER_IF_UP,
+ BAL_UTIL_OPER_IF_DOWN
+} bal_util_oper_if;
+
+/* flow request list,
+ */
+typedef enum
+{
+ BAL_UTIL_OPER_FLOW_ADD,
+ BAL_UTIL_OPER_FLOW_REMOVE,
+ BAL_UTIL_OPER_FLOW_CLEAR
+} bal_util_oper_flow;
+
+typedef enum
+{
+ BAL_UTIL_FLOW_IND_SEND_NONE,
+ BAL_UTIL_FLOW_IND_SEND_SUCCESS,
+ BAL_UTIL_FLOW_IND_SEND_FAIL
+} bal_util_flow_ind;
+
+/* group request list,
+ */
+typedef enum
+{
+ BAL_UTIL_OPER_GROUP_CREATE,
+ BAL_UTIL_OPER_GROUP_ADD,
+ BAL_UTIL_OPER_GROUP_REMOVE,
+ BAL_UTIL_OPER_GROUP_SET,
+ BAL_UTIL_OPER_GROUP_DESTROY
+} bal_util_oper_group;
+
+typedef enum
+{
+ BAL_UTIL_OPER_AGG_PORT_ADD,
+ BAL_UTIL_OPER_AGG_PORT_REMOVE,
+ BAL_UTIL_OPER_AGG_PORT_CLEAR
+} bal_util_oper_agg_port;
+
+/* Macro to retrieve the name string of the GROUP oper */
+#define BCMBAL_UTIL_GROUP_OPER_STR_GET(__op_type__) \
+ ( BAL_UTIL_OPER_GROUP_CREATE == __op_type__ ) ? "create" : \
+ ( BAL_UTIL_OPER_GROUP_ADD == __op_type__ ) ? "add" : \
+ ( BAL_UTIL_OPER_GROUP_REMOVE == __op_type__ ) ? "remove" : \
+ ( BAL_UTIL_OPER_GROUP_SET == __op_type__ ) ? "set" : \
+ ( BAL_UTIL_OPER_GROUP_DESTROY == __op_type__ ) ? "destroy" : \
+ "unknown"
+
+/* bal_app_msg_obj_key_t allow applications to id which instance of object
+ * this message should be processed
+ */
+typedef union bal_util_msg_obj_key
+{
+ bcmbal_access_terminal_key acc_term_key;
+ bcmbal_interface_key if_key;
+ bcmbal_subscriber_terminal_key sub_term_key;
+ bcmbal_flow_key flow_key;
+ bcmbal_group_key group_key;
+ bcmbal_tm_sched_key tm_sched_key;
+} bal_util_msg_obj_key;
+
+#define BCMBAL_INVALID_TUNNEL_ID 0xffffffff
+
+ /* indication message header */
+ typedef struct bal_util_msg_ind
+ {
+ bal_comm_msg_hdr comm_hdr; /* Communication header */
+ uint32_t version; /* version of the app message format */
+ bal_util_msg_obj_key obj_key;
+ int32_t status; /* bcmos_errno */
+ /* Optional custom BAL MAC/SWITCH UTIL indication data follows */
+ char data[0];
+ } bal_util_msg_ind;
+
+ /* auto indication message header */
+ typedef bal_util_msg_ind bal_util_msg_auto_ind;
+
+#endif /* _BAL_UTIL_MSG_H */
diff --git a/bal_release/src/common/include/bal_version.h b/bal_release/src/common/include/bal_version.h
new file mode 100644
index 0000000..533ff6b
--- /dev/null
+++ b/bal_release/src/common/include/bal_version.h
@@ -0,0 +1,44 @@
+/*************************************************************
+ * DO NOT EDIT! THIS FILE WAS AUTO GENERATED. DO NOT EDIT! *
+ *************************************************************/
+/******************************************************************************
+ *
+ * <:copyright-BRCM:2017:DUAL/GPL:standard
+ *
+ * Copyright (c) 2017 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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+#if !defined(BAL_VERSION_H)
+#define BAL_VERSION_H
+
+#define BAL_VERSION "R02.02.01.139177"
+#define BAL_VERSION_STR_LEN (17)
+
+#define BAL_BUILD_DATE "Thu Mar 30 18:15:35 IDT 2017"
+#define BAL_BUILD_INFO ""
+
+#endif /* BAL_VERSION_H */
diff --git a/bal_release/src/common/os_abstraction/Makefile b/bal_release/src/common/os_abstraction/Makefile
new file mode 120000
index 0000000..823d78c
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/Makefile
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/Makefile
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_common.c b/bal_release/src/common/os_abstraction/bcmos_common.c
new file mode 120000
index 0000000..eccb2aa
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_common.c
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_common.c
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_common.h b/bal_release/src/common/os_abstraction/bcmos_common.h
new file mode 120000
index 0000000..a31747a
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_common.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_common.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_common2.h b/bal_release/src/common/os_abstraction/bcmos_common2.h
new file mode 120000
index 0000000..b5d6f8f
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_common2.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_common2.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_endian.h b/bal_release/src/common/os_abstraction/bcmos_endian.h
new file mode 120000
index 0000000..3c1036d
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_endian.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_endian.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_errno.c b/bal_release/src/common/os_abstraction/bcmos_errno.c
new file mode 120000
index 0000000..240256f
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_errno.c
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_errno.c
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_errno.h b/bal_release/src/common/os_abstraction/bcmos_errno.h
new file mode 120000
index 0000000..9bac886
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_errno.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_errno.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_hash_table.c b/bal_release/src/common/os_abstraction/bcmos_hash_table.c
new file mode 120000
index 0000000..81cb3c0
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_hash_table.c
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_hash_table.c
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_hash_table.h b/bal_release/src/common/os_abstraction/bcmos_hash_table.h
new file mode 120000
index 0000000..c0111be
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_hash_table.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_hash_table.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_pack.h b/bal_release/src/common/os_abstraction/bcmos_pack.h
new file mode 120000
index 0000000..7582ed1
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_pack.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_pack.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_queue.h b/bal_release/src/common/os_abstraction/bcmos_queue.h
new file mode 120000
index 0000000..cf2d81d
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_queue.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_queue.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_rw_lock.c b/bal_release/src/common/os_abstraction/bcmos_rw_lock.c
new file mode 120000
index 0000000..bee8c23
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_rw_lock.c
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_rw_lock.c
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_rw_lock.h b/bal_release/src/common/os_abstraction/bcmos_rw_lock.h
new file mode 120000
index 0000000..cd9e84d
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_rw_lock.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_rw_lock.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_sysif.h b/bal_release/src/common/os_abstraction/bcmos_sysif.h
new file mode 120000
index 0000000..a9c8db8
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_sysif.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_sysif.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_tree.h b/bal_release/src/common/os_abstraction/bcmos_tree.h
new file mode 120000
index 0000000..62433e7
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_tree.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_tree.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/bcmos_types.h b/bal_release/src/common/os_abstraction/bcmos_types.h
new file mode 120000
index 0000000..5e43582
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/bcmos_types.h
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/bcmos_types.h
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/cfe b/bal_release/src/common/os_abstraction/cfe
new file mode 120000
index 0000000..5dba27e
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/cfe
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/cfe
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/linux b/bal_release/src/common/os_abstraction/linux
new file mode 120000
index 0000000..ee2249d
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/linux
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/linux
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/os_cli b/bal_release/src/common/os_abstraction/os_cli
new file mode 120000
index 0000000..075f9b4
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/os_cli
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/os_cli
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/posix b/bal_release/src/common/os_abstraction/posix
new file mode 120000
index 0000000..9f04fee
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/posix
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/posix
\ No newline at end of file
diff --git a/bal_release/src/common/os_abstraction/vxworks55 b/bal_release/src/common/os_abstraction/vxworks55
new file mode 120000
index 0000000..5a3b0c5
--- /dev/null
+++ b/bal_release/src/common/os_abstraction/vxworks55
@@ -0,0 +1 @@
+../../../3rdparty/maple/sdk/host_customized/os_abstraction/vxworks55
\ No newline at end of file
diff --git a/bal_release/src/common/utils b/bal_release/src/common/utils
new file mode 120000
index 0000000..1d7a58c
--- /dev/null
+++ b/bal_release/src/common/utils
@@ -0,0 +1 @@
+../../3rdparty/maple/sdk/host_driver/utils
\ No newline at end of file
diff --git a/bal_release/src/core/main/Makefile b/bal_release/src/core/main/Makefile
new file mode 100644
index 0000000..d0a6e02
--- /dev/null
+++ b/bal_release/src/core/main/Makefile
@@ -0,0 +1,39 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# BAL core CLI application
+#
+MOD_NAME = bal_core
+MOD_DEPS = common_include dev_log cli os_cli bal_api bal_api_cli bal_mac_util bal_switch_util bal_app_utils rscmgr balobjmsg topology cmdline
+MOD_DEPS_OPT = omcisvc
+
+MOD_TYPE = lib
+
+srcs = bal_core.c bal_cli.c bal_worker.c acc_term_fsm.c sub_term_fsm.c flow_fsm.c fsm_common.c group_fsm.c tm_sched_fsm.c tm_queue_fsm.c
diff --git a/bal_release/src/core/main/acc_term_fsm.c b/bal_release/src/core/main/acc_term_fsm.c
new file mode 100644
index 0000000..c4635b9
--- /dev/null
+++ b/bal_release/src/core/main/acc_term_fsm.c
@@ -0,0 +1,2431 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file acc_term_fsm.c
+ * @brief Code to support the BAL access terminal FSM
+ *
+ * @addtogroup access_terminal
+ */
+
+/*@{*/
+
+#define BAL_DBG_PRINT
+
+/*--- project includes ---*/
+#include <bcmos_system.h>
+#include <acc_term_fsm.h>
+#include <bal_msg.h>
+#include <bal_api.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include <bal_osmsg.h>
+#include <fsm_common.h>
+#include <rsc_mgr.h>
+#include <bal_core.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+/*
+ * @brief The logging device ids for the access-terminal and interface
+ */
+static dev_log_id log_id_access_terminal;
+static dev_log_id log_id_interface;
+#endif
+
+
+/*--- local function declarations ---*/
+static bcmos_errno acc_term_fsm_acc_term_admin_up_ok(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_acc_term_admin_dn_start(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_acc_term_admin_dn_ok(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_ignore_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_acc_term_admin_up_pending(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_acc_term_admin_dn_pending(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_adding_process_util_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_removing_process_util_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_process_util_auto_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_process_adding_timeout(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_process_removing_timeout(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno acc_term_fsm_acc_term_admin_up_start(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static bcmos_errno interface_admin_up_start(acc_term_interface *p_interface,
+ void *msg);
+
+static bcmos_errno interface_admin_dn_start(acc_term_interface *p_interface,
+ void *msg);
+
+static bcmos_timer_rc acc_term_fsm_timer_expiry(bcmos_timer *timer, long pUser);
+
+static bcmos_errno access_terminal_fsm_exec(acc_term_inst *p_acc_term_inst, acc_term_fsm_event *p_event);
+
+
+/**
+ * access-terminal FSM helper functions
+ */
+static bcmos_errno acc_term_fsm_state_err(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event);
+
+static void initialize_access_terminal_instance_config(acc_term_inst *p_acc_term_inst);
+
+static bcmos_errno sub_term_id_list_fill(uint32_t interface_index,
+ bcmbal_sub_id_list_u16 *sub_term_id_list);
+
+
+static acc_term_inst *access_terminal_get(void);
+static char *interface_type_str_get(bcmbal_intf_type intf_type);
+
+static bcmos_errno interface_tm_sched_set(bcmbal_interface_cfg *p_interface_info);
+static acc_term_interface * bcmbal_interface_get(bcmbal_interface_key key);
+
+#define ACC_TERM_FSM_STATE_ADDING_TIMEOUT (45) /* Seconds */
+
+/*
+ * @brief The definition of an access terminal FSM state processing function
+ */
+typedef bcmos_errno (* acc_term_fsm_state_processor)(acc_term_inst *, void *, acc_term_fsm_event *);
+
+extern bcmbal_config_params bal_config_params;
+
+
+/**
+ * @brief API to get oper status from admin state of an interface
+ */
+bcmbal_status bcmbal_get_intf_oper_status_from_admin_state (bcmbal_state intf_admin_state)
+{
+ switch (intf_admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ return BCMBAL_STATUS_UP;
+ break;
+
+ case BCMBAL_STATE_DOWN:
+ return BCMBAL_STATUS_DOWN;
+ break;
+
+ case BCMBAL_STATE_TESTING:
+ return BCMBAL_STATUS_TESTING;
+ break;
+
+ default:
+ return BCMBAL_STATUS_UP; /* default keep oper status as UP */
+ break;
+ }
+
+ return BCMBAL_STATUS_UP; /* default keep oper status as UP */
+}
+
+
+/**
+ * @brief API to convert port type and id from CLI/Mgmt interface to the internal
+ * index of interface array database.
+ */
+uint32_t bcmbal_port_type_and_id_to_interface_index (bcmbal_intf_type intf_type, bcmbal_intf_id intf_id)
+{
+ switch (intf_type)
+ {
+ case BCMBAL_INTF_TYPE_PON:
+ if (intf_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES)
+ {
+ return intf_id; /* zero offset for the PON ports */
+ }
+ break;
+
+ case BCMBAL_INTF_TYPE_NNI:
+ if (intf_id < bal_config_params.num_nni_ports)
+ {
+ return (NUM_SUPPORTED_SUBSCRIBER_INTERFACES + intf_id); /* offset-ed for the NNI ports */
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return INVALID_INTERFACE_INDEX;
+
+}
+
+
+/*
+ * @brief The Access terminal FSM state processing array
+ */
+static acc_term_fsm_state_processor access_term_states[ACC_TERM_FSM_STATE__NUM_OF][ACC_TERM_FSM_EVENT_TYPE__NUM_OF] =
+{
+
+ [ACC_TERM_FSM_STATE_NULL] =
+ {
+ /*
+ * Next state: ADDING
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP] = acc_term_fsm_acc_term_admin_up_start,
+
+ /*
+ * Next state: NULL
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN] = acc_term_fsm_acc_term_admin_dn_ok,
+
+ /*
+ * Next state: NULL
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_ignore_msg,
+
+ /*
+ * Next state: NULL
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg,
+ },
+
+ [ACC_TERM_FSM_STATE_ADDING] =
+ {
+ /*
+ * Next state: ADDING
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP] = acc_term_fsm_acc_term_admin_up_pending,
+
+ /*
+ * Next state: ADDING | ADDED
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_adding_process_util_msg,
+
+ /*
+ * Next state: ADDING
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg,
+
+ /*
+ * Next state: NULL
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_TIMEOUT] = acc_term_fsm_process_adding_timeout,
+
+ },
+
+ [ACC_TERM_FSM_STATE_ADDED] =
+ {
+ /*
+ * Next state: ADDED
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP] = acc_term_fsm_acc_term_admin_up_ok,
+
+ /*
+ * Next state: REMOVING
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN] = acc_term_fsm_acc_term_admin_dn_start,
+
+ /*
+ * Next state: ADDING | ADDED
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_ignore_msg,
+
+ /*
+ * Next state: ADDED
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg,
+
+ },
+
+ [ACC_TERM_FSM_STATE_REMOVING] =
+ {
+ /*
+ * Next state: REMOVING
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN] = acc_term_fsm_acc_term_admin_dn_pending,
+
+ /*
+ * Next state: REMOVING | NULL
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_removing_process_util_msg,
+
+ /*
+ * Next state: REMOVING
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg,
+
+ /*
+ * Next state: NULL
+ */
+ [ACC_TERM_FSM_EVENT_TYPE_TIMEOUT] = acc_term_fsm_process_removing_timeout,
+ },
+
+};
+
+static char *state_name_str[] =
+{
+ "ACC_TERM_NULL",
+ "ACC_TERM_ADDING",
+ "ACC_TERM_ADDED",
+ "ACC_TERM_REMOVING",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (ACC_TERM_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), acc_term_fsm_state);
+
+static char *acc_term_state_name_get(acc_term_fsm_state state)
+{
+ if(state < ACC_TERM_FSM_STATE__LAST)
+ {
+ return state_name_str[state];
+ }
+ else
+ {
+ return "ACC_TERM_UNKNOWN";
+ }
+}
+
+static char *event_name_str[] =
+{
+ "ACC_TERM_FSM_ACC_TERM_ADMIN_UP_EVENT",
+ "ACC_TERM_FSM_ACC_TERM_ADMIN_DN_EVENT",
+ "ACC_TERM_FSM_INT_ADMIN_UP_EVENT",
+ "ACC_TERM_FSM_INT_ADMIN_DN_EVENT",
+ "ACC_TERM_FSM_UTIL_MSG_EVENT",
+ "ACC_TERM_FSM_UTIL_AUTO_MSG_EVENT",
+ "ACC_TERM_FSM_TIMEOUT_EVENT"
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (ACC_TERM_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), acc_term_fsm_event_type);
+
+static char *acc_term_event_name_get(acc_term_fsm_event_type event)
+{
+ if(event < ACC_TERM_FSM_EVENT_TYPE__LAST)
+ {
+ return event_name_str[event];
+ }
+ else
+ {
+ return "ACC_TERM_EVT_UNKNOWN";
+ }
+}
+
+static acc_term_inst single_access_terminal_instance;
+
+/*****************************************************************************/
+/**
+ * @brief A function called to initialize the access-terminal FSM
+ * infrastructure.
+ *
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @returns void
+ *****************************************************************************/
+void access_terminal_fsm_init(void)
+{
+
+#ifdef ENABLE_LOG
+ /* Register the log ids for this FSM */
+ log_id_access_terminal = bcm_dev_log_id_register("ACC_TERM", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_access_terminal == DEV_LOG_INVALID_ID);
+
+ log_id_interface = bcm_dev_log_id_register("INTF", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_interface == DEV_LOG_INVALID_ID);
+#endif
+
+ /*
+ * Initialize the access terminal instance structures
+ */
+ initialize_access_terminal_instance_config(&single_access_terminal_instance);
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing executive function
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno access_terminal_fsm_exec(acc_term_inst *p_acc_term_inst,
+ acc_term_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ acc_term_fsm_state pre_state;
+ acc_term_fsm_state_processor acc_term_state_processor;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_acc_term_inst);
+ BUG_ON(NULL == p_event);
+
+ /* Record the present state before transitioning
+ */
+ pre_state = p_acc_term_inst->fsm_state;
+
+ /*
+ * Get the state processing function
+ */
+ acc_term_state_processor = access_term_states[p_acc_term_inst->fsm_state][p_event->event_type];
+
+ /*
+ * If there's a state processing function for this event and state, execute it.
+ * Otherwise, process a generic error.
+ */
+ if (acc_term_state_processor)
+ {
+ ret = acc_term_state_processor(p_acc_term_inst, p_event->msg, p_event);
+ } else
+ {
+ acc_term_fsm_state_err(p_acc_term_inst, p_event->msg, p_event);
+ }
+
+ BCM_LOG(DEBUG, log_id_access_terminal, "*** FSM exec: Event %s, State: %s --> %s\n",
+ acc_term_event_name_get(p_event->event_type),
+ acc_term_state_name_get(pre_state),
+ acc_term_state_name_get(p_acc_term_inst->fsm_state));
+
+ return ret;
+}
+
+bcmos_errno process_access_terminal_util_msg(void *msg_payload)
+{
+ acc_term_inst *p_access_terminal_inst;
+
+ BCM_LOG(INFO, log_id_access_terminal, "ACCESS_TERMINAL indication received from util\n");
+
+ /* Find the specified access terminal instance */
+ p_access_terminal_inst = access_terminal_get();
+
+ if (NULL != p_access_terminal_inst)
+ {
+ acc_term_fsm_event event;
+
+ event.event_type = ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG;
+ event.msg = msg_payload;
+
+ access_terminal_fsm_exec(p_access_terminal_inst, &event);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_interface, "Could not find the ACTIVE access-terminal\n");
+ }
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing for an access-terminal
+ * admin-up command received from the BAL Public API when the specified
+ * access-terminal instance is in the admin-down state (i.e. when
+ * the access-terminal instance FSM is in the NULL state).
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_acc_term_admin_up_start(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ acc_term_fsm_state old_state = p_acc_term_inst->fsm_state;
+
+ BCM_LOG(INFO, log_id_access_terminal,
+ "Received an admin UP request from BAL API - bringing access terminal up\n");
+
+ do
+ {
+ /* change access terminal state to ADDING */
+ p_acc_term_inst->fsm_state = ACC_TERM_FSM_STATE_ADDING;
+
+ /* start the timeout timer for the ADDING state */
+ fsm_timer_start(&p_acc_term_inst->timer_info,
+ p_acc_term_inst,
+ acc_term_fsm_timer_expiry,
+ TIMER_DURATION_IN_SEC(ACC_TERM_FSM_STATE_ADDING_TIMEOUT),
+ log_id_access_terminal);
+
+ /* Validate that the OLT SW version that the Bal was compiled against matches
+ * the SW version of the actual OLT that the Bal works with. We assume that
+ * Device Id 0 has the same version as all other OLT devices */
+ if (!bcmbal_is_mac_in_loopback() &&
+ (BCM_ERR_OK != (ret = mac_util_access_terminal_sw_version_validate((bcmolt_devid) 0))))
+ {
+ BCM_LOG(ERROR, log_id_access_terminal, "mac_util_access_terminal_sw_version_validate(() failed. rc=%s\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /* Core calls Mac Utils to set the access-terminal parameters using the applicable SDK calls */
+ if(BCM_ERR_OK != (ret = mac_util_access_terminal_set(p_acc_term_inst, BAL_UTIL_OPER_ACC_TERM_CONNECT)))
+ {
+ BCM_LOG(ERROR, log_id_access_terminal, "mac_util_access_terminal_set(() failed. rc=%s\n", bcmos_strerror(ret));
+ break;
+ }
+
+ }while(0);
+
+ if(BCM_ERR_OK == ret)
+ {
+ /*
+ * The access-terminal object command has succeeded. The current object info
+ * becomes the commanded object info, except for the oper_status. This should
+ * be done atomically
+ */
+ memcpy(&p_acc_term_inst->current_acc_term_obj_info,
+ &p_acc_term_inst->api_req_acc_term_obj_info,
+ sizeof(p_acc_term_inst->api_req_acc_term_obj_info));
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_TRUE);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info,
+ access_terminal,
+ oper_status,
+ BCMBAL_STATUS_DOWN);
+ }
+ else
+ {
+ fsm_timer_stop(&p_acc_term_inst->timer_info);
+ p_acc_term_inst->fsm_state = old_state;
+ mgmt_msg_send_balapi_ind(ret, msg, log_id_access_terminal);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing for an access-terminal
+ * admin-up command from the BAL Public API when the specified
+ * access-terminal is already admin-up (i.e. when the specified
+ * access-terminal instance FSM is in the ADDED state).
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_acc_term_admin_up_ok(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "Received an admin UP request from BAL API - returning OK to the API"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing for an access-terminal
+ * admin-down command received from the BAL Public API when the specified
+ * access-terminal is admin-up (i.e when the specified access-terminal
+ * instance FSM is in the ADDED state).
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_acc_term_admin_dn_start(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "Received an admin DOWN request from BAL API - removing the access terminal\n");
+
+ /*
+ * @todo - complete the DOWN implementation - until then, return an error
+ */
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing for access-terminal
+ * admin-down command from the BAL Public API when the specified
+ * access-terminal is already admin-down.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_acc_term_admin_dn_ok(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "Received an admin DOWN request from BAL API - returning OK to the API"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing function to ignore a
+ * received message.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_ignore_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_access_terminal, "Ignoring message from BAL API \n");
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing function to process an
+ * access-terminal admin-up command from the BAL Public API when the
+ * specified access-terminal is in the REMOVING state.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_acc_term_admin_up_pending(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ " Received an admin UP request from BAL API - returning UP_PENDING to the API"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing function to process an
+ * access-terminal admin-down command from the BAL Public API when the
+ * specified access-terminal FSM is in the REMOVING state.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_acc_term_admin_dn_pending(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_IN_PROGRESS;
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ " Received an admin DOWN request from BAL API"
+ " - returning IN_PROGRESS to the API - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing function to process a
+ * message from one of the BAL apps when the specified access-terminal
+ * instance FSM is in the ADDING state.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_adding_process_util_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ flow_fsm_state next_state = ACC_TERM_FSM_STATE_NULL;
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_acc_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ ret = ind_msg->status;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "Received an IND message from BAL UTIL (%s) during ADDING state with status %s\n",
+ subsystem_str[bcmbal_sender_get(msg)],
+ bcmos_strerror(ret)
+ );
+ }
+
+ /*
+ * Stop the indication timer
+ */
+ fsm_timer_stop(&p_acc_term_inst->timer_info);
+
+ if(BCM_ERR_OK == ret)
+ {
+ /* Core calls Switch Utils to set the access-terminal parameters using the applicable SDK calls */
+ ret = sw_util_access_terminal_set(p_acc_term_inst, BAL_UTIL_OPER_ACC_TERM_CONNECT);
+ if (ret)
+ {
+ BCM_LOG(INFO, log_id_access_terminal,
+ "sw_util_access_terminal_set(() failed. rc=%s\n", bcmos_strerror(ret));
+ }
+
+ if(BCM_ERR_OK == ret)
+ {
+ uint32_t logical_pon;
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info,
+ access_terminal,
+ oper_status,
+ BCMBAL_STATUS_UP);
+
+ /*
+ * Initialize the resource manager only if at least of the PONs on the device is a GPON/XGPON/XGS/NGPON2 PON
+ */
+ BCM_TOPO_DEV_FOR_EACH_PON(0, logical_pon)
+ {
+ bcm_topo_pon_family pon_family = bcm_topo_pon_get_pon_family(logical_pon);
+
+ if (pon_family == BCM_TOPO_PON_FAMILY_GPON)
+ {
+ rsc_mgr_mac_init();
+ break;
+ }
+ }
+
+ /*
+ * Go to the ADDED state upon success
+ */
+ next_state = ACC_TERM_FSM_STATE_ADDED;
+
+
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_access_terminal,
+ " Failed in state %s;%s\n",
+ acc_term_state_name_get(p_acc_term_inst->fsm_state),
+ bcmos_strerror(ret));
+
+ /*
+ * Automatically return to the NULL state if an error occurs
+ */
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_FALSE);
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&p_acc_term_inst->current_acc_term_obj_info.hdr,
+ log_id_access_terminal);
+
+
+
+ }
+
+ p_acc_term_inst->fsm_state = next_state;
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing function to process a
+ * message from one of the BAL apps received when the specified
+ * access-terminal instance FSM is in the REMOVING state.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_removing_process_util_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_acc_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ ret = ind_msg->status;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ " Received an IND message from BAL UTIL (%s) during REMOVING state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing function to process an
+ * AUTO IND message from one of the BAL apps.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_process_util_auto_msg(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_acc_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(INFO, log_id_access_terminal,
+ " Received an AUTO IND message from BAL UTIL ()\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief Interface admin-up command received from the BAL Public API when
+ * the specified interface instance is in the admin-up state.
+ *
+ * @note This handler gets called for both PON and NNI type interfaces
+ *
+ * @param p_interface_inst Pointer to an interface instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno interface_admin_up_start(acc_term_interface *p_interface_inst,
+ void *msg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_interface_key *key = &(p_interface_inst->api_req_int_obj_info.key);
+
+ BCM_LOG(INFO, log_id_interface,
+ " Received an INTERFACE admin UP request from BAL API"
+ " - bringing interface (%s%d) UP \n",
+ interface_type_str_get(key->intf_type),
+ key->intf_id);
+
+ do
+ {
+ bcmbal_state old_admin_state = p_interface_inst->current_int_obj_info.data.admin_state;
+
+ /*
+ * Create a pointer to the interface instance specified by the user
+ */
+
+ /*
+ * If the user has set the min_data_agg_port_id attribute for the interface, then program the resource manager
+ * with this value. It will also be sent to the MAC device for any required programming there.
+ */
+ if ((BCMBAL_INTF_TYPE_PON == key->intf_type) &&
+ (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_interface_inst->api_req_int_obj_info,
+ interface,
+ min_data_agg_port_id)) &&
+ (BCM_ERR_OK != rsc_mgr_access_int_base_alloc_id_set(key->intf_id,
+ p_interface_inst->api_req_int_obj_info.data.min_data_agg_port_id)))
+ {
+ BCM_LOG(ERROR, log_id_access_terminal, "Error while setting base agg_port_id (%d) in the resource manager\n",
+ p_interface_inst->api_req_int_obj_info.data.min_data_agg_port_id);
+
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Change the interface admin state of the "current" interface object to up (this is for reporting) */
+ BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info,
+ interface,
+ admin_state,
+ BCMBAL_STATE_UP);
+
+ /* Core calls Mac Utils to set the interface parameters using the applicable SDK calls */
+ ret = mac_util_interface_set(p_interface_inst, BAL_UTIL_OPER_IF_UP);
+
+ if (BCM_ERR_OK != ret)
+ {
+ BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info,
+ interface,
+ admin_state,
+ old_admin_state);
+
+ BCM_LOG(ERROR, log_id_interface,
+ "Error detected by mac_util_interface_set (%s)\n",
+ bcmos_strerror(ret));
+
+ break;
+ }
+ } while (0);
+
+ if (BCM_ERR_OK != ret)
+ {
+ /* report this error to the API */
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_interface);
+ }
+ else
+ {
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_interface_inst->current_int_obj_info), BCMOS_TRUE);
+ }
+
+ return ret;
+ }
+
+/*****************************************************************************/
+/**
+ * @brief Interface admin-up command received from the BAL Public API when
+ * the specified interface instance is in the admin-down state.
+ *
+ * @note This handler gets called for both PON and NNI type interfaces
+ *
+ * @param p_interface_inst Pointer to an interface instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno interface_admin_dn_start(acc_term_interface *p_interface_inst,
+ void *msg)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_interface_key *key = &(p_interface_inst->api_req_int_obj_info.key);
+
+ BCM_LOG(INFO, log_id_interface,
+ " Received an INTERFACE admin DOWN request from BAL API"
+ " - bringing interface (%s%d) DOWN \n",
+ interface_type_str_get(key->intf_type),
+ key->intf_id);
+
+ do
+ {
+ bcmbal_state old_admin_state = p_interface_inst->current_int_obj_info.data.admin_state;
+
+ /*
+ * Create a pointer to the interface instance specified by the user
+ */
+
+ /* Core calls Mac Utils to set the interface parameters using the applicable SDK calls */
+ ret = mac_util_interface_set(p_interface_inst, BAL_UTIL_OPER_IF_DOWN);
+
+ if (BCM_ERR_OK != ret)
+ {
+
+ BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info,
+ interface,
+ admin_state,
+ old_admin_state);
+
+ BCM_LOG(ERROR, log_id_interface,
+ "Error detected by mac_util_interface_set (%s)\n",
+ bcmos_strerror(ret));
+
+ break;
+ }
+
+ } while (0);
+
+ /* Change the interface admin state of the current interface info to down */
+ BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info,
+ interface,
+ admin_state,
+ BCMBAL_STATE_DOWN);
+
+ /* Check for any error and send an indication immediately in that case */
+ if (BCM_ERR_OK != ret)
+ {
+ /* report this error to the API */
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_interface);
+
+ }
+ else
+ {
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_interface_inst->current_int_obj_info), BCMOS_TRUE);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The function to process a timer expiry for either the ADDING
+ * states. This function executes an
+ * ACC_TERM_FSM_TIMEOUT_EVENT in the FSM state machine.
+ *
+ * @param timer - A pointer to the timer instance
+ * @param pUser - An opaque pointer to an access terminal instance
+ *
+ * @returns bcmos_timer_rc == BCMOS_TIMER_OK
+ */
+static bcmos_timer_rc acc_term_fsm_timer_expiry(bcmos_timer *timer, long pUser)
+{
+ acc_term_fsm_event acc_term_event;
+
+ /*
+ * Stop the indication timer
+ */
+ fsm_timer_stop(timer);
+
+ BCM_LOG(INFO, log_id_access_terminal,
+ "timer expiry\n");
+
+ /*
+ * A message pointer is always passed inside the event structure. In this case, it is unused
+ */
+ acc_term_event.msg = NULL;
+ acc_term_event.event_type = ACC_TERM_FSM_EVENT_TYPE_TIMEOUT;
+
+ /* Declare this no longer in-progress */
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(((acc_term_inst *)pUser)->current_acc_term_obj_info), BCMOS_FALSE);
+
+ /*
+ * Run the access terminal FSM to process this event
+ */
+ access_terminal_fsm_exec((acc_term_inst *)pUser, &acc_term_event);
+
+ return BCMOS_TIMER_OK;
+
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing a timeout that occurs
+ * when the FSM is in the ADDING state. In this case, the FSM should
+ * just go back to the NULL state.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_process_adding_timeout(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "Error: Received a timeout while in the %s state.\n",
+ acc_term_state_name_get(p_acc_term_inst->fsm_state));
+
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(BCM_ERR_TIMEOUT,
+ (void *)&(p_acc_term_inst->current_acc_term_obj_info.hdr.hdr),
+ log_id_access_terminal);
+
+ /*
+ * Go back to the previous state
+ */
+ p_acc_term_inst->fsm_state = ACC_TERM_FSM_STATE_NULL;
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_FALSE);
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM state processing a timeout that occurs
+ * when the FSM is in the REMOVING state. In this case, the FSM should
+ * just go back to the ADDED state.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_process_removing_timeout(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_access_terminal,
+ "Received a timeout while in the %s state. Going back to the ADDED state\n",
+ acc_term_state_name_get(p_acc_term_inst->fsm_state));
+
+ /*
+ * Go back to the previous state
+ */
+ p_acc_term_inst->fsm_state = ACC_TERM_FSM_STATE_ADDED;
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The function to process a
+ * message from one of the BAL apps for the specified interface
+ *
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_interface_util_msg(void *msg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ uint32_t interface_index = INVALID_INTERFACE_INDEX;
+ bal_util_msg_ind *ind_msg;
+ acc_term_interface *p_interface_inst;
+
+ /* Parameter checks */
+ BUG_ON(NULL == msg);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ " Received an interface IND message from BAL UTIL (%s)\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ if (BCM_ERR_OK == ind_msg->status)
+ {
+ /* first get the index to the interface array from port id/type */
+ interface_index = bcmbal_port_type_and_id_to_interface_index(ind_msg->obj_key.if_key.intf_type,
+ ind_msg->obj_key.if_key.intf_id);
+
+ if (interface_index >= INVALID_INTERFACE_INDEX)
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "INVALID port type/id (%s/%d) to interface index (%d)\n",
+ interface_type_str_get(ind_msg->obj_key.if_key.intf_type),
+ ind_msg->obj_key.if_key.intf_id,
+ interface_index);
+
+ ret = BCM_ERR_PARM;
+ }
+
+ p_interface_inst = &(access_terminal_get()->intf_info.interface[interface_index]);
+
+ if(BCM_ERR_OK == ret)
+ {
+ /* Core calls Switch Utils to set the interface parameters using the applicable SDK call
+ * If a PON port is being set, then the corresponding direct connect switch port is also
+ * set along with it
+ */
+ ret = sw_util_interface_set(p_interface_inst,
+ (p_interface_inst->api_req_int_obj_info.data.admin_state == BCMBAL_STATE_DOWN ?
+ BAL_UTIL_OPER_IF_DOWN : BAL_UTIL_OPER_IF_UP));
+
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "sw_util_interface_set(() failed. rc=%s\n", bcmos_strerror(ret));
+
+ }
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_interface,
+ "Bad interface index: interface type/id (%s/%d) (status: %s)\n",
+ interface_type_str_get(ind_msg->obj_key.if_key.intf_type),
+ ind_msg->obj_key.if_key.intf_id,
+ bcmos_strerror(ind_msg->status));
+ }
+
+
+
+ if(BCM_ERR_OK == ret)
+ {
+ BCM_LOG(DEBUG, log_id_interface,
+ "Setting interface (%d) to %s\n",
+ interface_index,
+ (BCMBAL_STATE_UP == p_interface_inst->api_req_int_obj_info.data.admin_state) ?
+ "UP" : "DOWN");
+
+
+ /*
+ * Interface SET function succeeded, so copy the API request into the
+ * current interface object.
+ */
+
+ bcmbal_interface_object_overlay_w_src_priority(&(p_interface_inst->current_int_obj_info),&(p_interface_inst->api_req_int_obj_info));
+
+ /* Set the status of the current interface that we just configured to the requested state (UP or DOWN) */
+ BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info,
+ interface,
+ oper_status,
+ bcmbal_get_intf_oper_status_from_admin_state(p_interface_inst->api_req_int_obj_info.data.admin_state));
+
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_interface,
+ "Bad response from switch: Interface type/Id: %s/%d (status:%s) \n",
+ interface_type_str_get(ind_msg->obj_key.if_key.intf_type),
+ ind_msg->obj_key.if_key.intf_id,
+ bcmos_strerror(ind_msg->status));
+
+ }
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_interface,
+ "Bad interface indication from MAC (status:%s)\n",
+ bcmos_strerror(ind_msg->status));
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_interface_inst->current_int_obj_info), BCMOS_FALSE);
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&(p_interface_inst->current_int_obj_info.hdr),
+ log_id_interface);
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Access terminal FSM function which is executed when an error
+ * is encountered during FSM processing.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ * @param msg Pointer to a BAL message (MAY BE NULL!)
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno acc_term_fsm_state_err(acc_term_inst *p_acc_term_inst,
+ void *msg,
+ acc_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_INVALID_OP;
+
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "Error encountered processing FSM - BAD EVENT event:%s, state:%s\n",
+ acc_term_event_name_get(p_event->event_type),
+ acc_term_state_name_get(p_acc_term_inst->fsm_state));
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function called by the core worker thread to process an
+ * access-terminal object message (SET, GET, CLEAR, STATS) received
+ * from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_access_terminal_object(void *msg_payload)
+{
+
+ bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
+ acc_term_inst *p_access_terminal_inst;
+ acc_term_fsm_event acc_term_event;
+ bcmbal_obj_msg_type oper_type;
+
+ /* Parameter checks */
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "Processing an access-terminal object\n");
+
+ do
+ {
+ /*
+ * Find or create the specified access terminal instance
+ */
+ p_access_terminal_inst = access_terminal_get();
+
+ oper_type = ((bcmbal_access_terminal_cfg *)msg_payload)->hdr.hdr.type;
+
+ /* If the state of the access-terminal is in flux, then reject the SET request */
+ if(BCMBAL_OBJ_MSG_TYPE_SET == oper_type &&
+ BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_access_terminal_inst->current_acc_term_obj_info)))
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "The access-terminal is in-progress, SETs are not allowed\n");
+ ret = BCM_ERR_IN_PROGRESS;
+ break;
+ }
+
+ /* Copy the object in the message into local storage */
+ memcpy(&p_access_terminal_inst->api_req_acc_term_obj_info,
+ msg_payload,
+ sizeof(p_access_terminal_inst->api_req_acc_term_obj_info));
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "access_terminal admin state is: %s\n",
+ (BCMBAL_STATE_UP == p_access_terminal_inst->api_req_acc_term_obj_info.data.admin_state) ?
+ "UP" : "DOWN");
+
+ /*
+ * A message pointer is always passed inside the event structure.
+ */
+ acc_term_event.msg = msg_payload;
+
+ /* SET or GET or ...? */
+ switch (oper_type)
+ {
+ case (BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "Processing a access-terminal SET REQ mgmt message\n");
+
+ /*
+ * Check if the mandatory access-terminal attributes have been set
+ */
+
+ do
+ {
+
+ /* The admin state attribute is mandatory */
+ if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(&p_access_terminal_inst->api_req_acc_term_obj_info,
+ access_terminal,
+ admin_state))
+ {
+ ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+
+ /*set iwf_mode from the global config parameters*/
+ BCMBAL_CFG_PROP_SET(&p_access_terminal_inst->api_req_acc_term_obj_info,
+ access_terminal,
+ iwf_mode,
+ bcmbal_config_get()->iwf_mode);
+
+ /*
+ * Perform the validation check(s) that the utils require
+ */
+ if(BCM_ERR_OK !=
+ (ret = mac_util_access_terminal_info_validate(&p_access_terminal_inst->api_req_acc_term_obj_info)))
+ {
+ break;
+ }
+ }
+ while(0);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ rsp_ret = mgmt_msg_send_balapi_rsp(ret,
+ msg_payload,
+ oper_type,
+ log_id_access_terminal);
+
+ if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
+ {
+ /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
+ ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
+ break;
+ }
+
+ /* Reflect the admin state of the access-terminal according to the commanded admin state */
+ BCMBAL_CFG_PROP_SET(&p_access_terminal_inst->current_acc_term_obj_info,
+ access_terminal,
+ admin_state,
+ p_access_terminal_inst->api_req_acc_term_obj_info.data.admin_state);
+
+ if(BCMBAL_STATE_UP == p_access_terminal_inst->api_req_acc_term_obj_info.data.admin_state)
+ {
+
+ acc_term_event.event_type = ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP;
+ }
+ else
+ {
+ acc_term_event.event_type = ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN;
+ }
+
+ /*
+ * Run the access terminal FSM to process this event
+ */
+ ret = access_terminal_fsm_exec(p_access_terminal_inst, &acc_term_event);
+ break;
+
+ }
+ case (BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "Processing a access-terminal GET REQ mgmt message\n");
+
+ p_access_terminal_inst->current_acc_term_obj_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+ *((bcmbal_access_terminal_cfg *)msg_payload) = p_access_terminal_inst->current_acc_term_obj_info;
+
+ mgmt_msg_send_balapi_rsp(ret,
+ msg_payload,
+ oper_type,
+ log_id_access_terminal);
+ break;
+
+ }
+ default:
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "Unsupported operation on access-terminal object (%d)\n",
+ bcmbal_msg_id_oper_get(msg_payload));
+
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_access_terminal);
+
+ break;
+ }
+ }
+ }while(0);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve an access-terminal instance
+ *
+ * @returns acc_term_inst_t* A pointer to the found access-terminal instance,
+ * or NULL if one is not found.
+ *****************************************************************************/
+static acc_term_inst *access_terminal_get(void)
+{
+ acc_term_inst *p_acc_term = (acc_term_inst *)NULL;
+
+ p_acc_term = &single_access_terminal_instance;
+
+ return p_acc_term;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve the status of the access-terminal
+ *
+ *
+ * @returns bcmbal_status
+ *****************************************************************************/
+bcmbal_status acc_term_status_get(void)
+{
+ acc_term_inst *p_acc_term_inst;
+
+ p_acc_term_inst = access_terminal_get();
+
+ return p_acc_term_inst->current_acc_term_obj_info.data.oper_status;
+
+}
+
+static bcmos_errno interface_tm_sched_set(bcmbal_interface_cfg *p_interface_info)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *p_tm_sched_inst;
+ bcmbal_tm_sched_key tm_key;
+ switch(p_interface_info->key.intf_type)
+ {
+ case BCMBAL_INTF_TYPE_PON:
+ {
+ /*for active pon interface:
+ ds_tm should be define, - if it is set, validate sched exist and match direction (ds)
+ if not set - will create auto created tm */
+ if(BCMBAL_CFG_PROP_IS_SET(p_interface_info,interface,ds_tm))
+ {
+ tm_key.dir = BCMBAL_TM_SCHED_DIR_DS;
+ tm_key.id = p_interface_info->data.ds_tm;
+ p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_interface, "there is no ds tm sched with id %d", tm_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d",
+ p_interface_info->key.intf_id, tm_key.id);
+ break;
+ }
+ }
+ else /*auto created sched was removed and no other default sched was set*/
+ {
+ BCM_LOG(ERROR, log_id_interface, "default tm node must be set! ");
+ ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+ /* us_tm is optional - if it is set, validate sched exist and match direction (us)*/
+ if(BCMBAL_CFG_PROP_IS_SET(p_interface_info, interface, us_tm))
+ {
+ tm_key.dir = BCMBAL_TM_SCHED_DIR_US;
+ tm_key.id = p_interface_info->data.us_tm;
+ p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_interface, "there is no us tm sched with id %d", tm_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d",
+ p_interface_info->key.intf_id, tm_key.id);
+ break;
+ }
+ }
+
+ }
+ break;
+
+ case BCMBAL_INTF_TYPE_NNI:
+ {
+ /*for active nni interface:
+ us_tm should be define, -
+ if it is set, validate sched exist and match direction (us)
+ if not set - will create auto created tm
+ */
+ if(BCMBAL_CFG_PROP_IS_SET(p_interface_info, interface, us_tm))
+ {
+ tm_key.dir = BCMBAL_TM_SCHED_DIR_US;
+ tm_key.id = p_interface_info->data.us_tm;
+ p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_interface, "there is no us tm sched with id %d", tm_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d",
+ p_interface_info->key.intf_id, tm_key.id);
+ break;
+ }
+ }
+ else /*auto created sched was removed and no other default sched was set*/
+ {
+ BCM_LOG(ERROR, log_id_interface, "default tm node must be set! ");
+ break;
+ }
+ /* ds_tm is optional - if it is set, validate sched exist and match direction (ds)*/
+ if(BCMBAL_CFG_PROP_IS_SET(p_interface_info, interface, ds_tm))
+ {
+ tm_key.dir = BCMBAL_TM_SCHED_DIR_DS;
+ tm_key.id = p_interface_info->data.ds_tm;
+ p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_interface, "there is no ds tm sched with id %d", tm_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d",
+ p_interface_info->key.intf_id, tm_key.id);
+ break;
+ }
+ }
+ }
+ break;
+
+ default:
+ BCM_LOG(ERROR, log_id_interface, "Invalid intf type (%d) in interface key\n",
+ p_interface_info->key.intf_type);
+ ret = BCM_ERR_PARM;
+ }
+ return ret;
+}
+
+bcmos_errno interface_tm_sched_unset(bcmbal_interface_key intf_key, bcmbal_tm_sched_key sched_key)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ acc_term_interface *p_acc_term_interface = bcmbal_interface_get(intf_key);
+ do
+ {
+ if(NULL == p_acc_term_interface)
+ {
+ BCM_LOG(ERROR, log_id_interface, "no such interface (id = %d dir = %s ) \n",
+ intf_key.intf_id, interface_type_str_get(intf_key.intf_type));
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ if (BCMBAL_TM_SCHED_DIR_US == sched_key.dir)
+ {
+ BCMBAL_CFG_PROP_CLEAR(&(p_acc_term_interface->current_int_obj_info), interface, us_tm);
+ }
+ else
+ {
+ BCMBAL_CFG_PROP_CLEAR(&(p_acc_term_interface->current_int_obj_info), interface, ds_tm);
+ }
+ }while(0);
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to process an interface object message
+ * (SET, GET, CLEAR, STATS) received from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_interface_object(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ bcmbal_interface_cfg *p_intf_cfg = (bcmbal_interface_cfg *)msg_payload;
+ bcmbal_interface_key *p_intf_key;
+ acc_term_inst *p_access_terminal_inst;
+
+ bcmbal_interface_cfg *p_api_req_interface_info;
+ bcmbal_interface_cfg *p_current_interface_info;
+ uint32_t interface_index = INVALID_INTERFACE_INDEX;
+ bcmbal_obj_msg_type oper_type;
+
+ BCM_LOG(DEBUG, log_id_interface,
+ "Processing an interface object\n");
+
+ do
+ {
+ do
+ {
+ oper_type = p_intf_cfg->hdr.hdr.type;
+
+ /*
+ * See if the access terminal is active
+ */
+ p_access_terminal_inst = access_terminal_get();
+
+ if(NULL == p_access_terminal_inst)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "the access-terminal is not active\n");
+
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* If the state of the access-terminal is in flux, then reject the SET request */
+ if(BCMBAL_OBJ_MSG_TYPE_SET == oper_type &&
+ BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_access_terminal_inst->current_acc_term_obj_info)))
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "The access-terminal is in-progress, SETs to an interface are not allowed\n");
+
+ ret = BCM_ERR_IN_PROGRESS;
+ break;
+ }
+
+ /*
+ * Get the interface key from the message
+ */
+ p_intf_key = &p_intf_cfg->key;
+
+ if (p_intf_key->intf_type == BCMBAL_INTF_TYPE_PON)
+ {
+ if(p_intf_key->intf_id > NUM_SUPPORTED_SUBSCRIBER_INTERFACES)
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "out of range value (%d) detected in interface key for PON\n", p_intf_key->intf_id);
+
+ ret = BCM_ERR_RANGE;
+ break;
+ }
+ }
+ /** @todo check the lower limit also */
+ else if (p_intf_key->intf_type == BCMBAL_INTF_TYPE_NNI)
+ {
+ if( BCMOS_FALSE == bcm_topo_nni_is_valid(p_intf_key->intf_id))
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "out of range value (%d) detected in interface key for NNI\n", p_intf_key->intf_id);
+
+ ret = BCM_ERR_RANGE;
+ break;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "Invalid intf type (%d) in interface key\n", p_intf_key->intf_type);
+
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /*
+ * Don't accept interface object references when the associated access-terminal is down
+ *
+ * Interfaces are not even instantiated internally until the access-terminal object to which
+ * they belong is instantiated.
+ */
+ if(BCMBAL_STATE_DOWN == p_access_terminal_inst->current_acc_term_obj_info.data.admin_state)
+ {
+ BCM_LOG(INFO, log_id_interface,
+ "access terminal admin-state is DOWN\n");
+
+ ret = BCM_ERR_INVALID_OP;
+ break;
+ }
+
+ /* Get the index to the interface array from port id/type */
+ interface_index = bcmbal_port_type_and_id_to_interface_index (p_intf_key->intf_type, p_intf_key->intf_id);
+ if (interface_index >= INVALID_INTERFACE_INDEX)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "INVALID port type/id (%s/%d) to interface index (%d) for access terminal\n",
+ interface_type_str_get(p_intf_key->intf_type), p_intf_key->intf_id, interface_index);
+
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /*
+ * This is a pointer to the "API interface" structure
+ */
+ p_api_req_interface_info =
+ &(p_access_terminal_inst->intf_info.interface[interface_index].api_req_int_obj_info);
+
+ /*
+ * This is a pointer to the "current interface" structure
+ */
+ p_current_interface_info =
+ &(p_access_terminal_inst->intf_info.interface[interface_index].current_int_obj_info);
+
+ /* If the state of the interface is in flux, then reject the SET request */
+ if(BCMBAL_OBJ_MSG_TYPE_SET == oper_type &&
+ (BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(p_current_interface_info)))
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "The interface is in-progress, SETs are not allowed\n");
+ ret = BCM_ERR_IN_PROGRESS;
+ break;
+ }
+
+ }while(0);
+
+ if(BCM_ERR_OK != ret)
+ {
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface);
+ break;
+ }
+
+ /*
+ * Fill in the interface info SET data structure
+ */
+ *p_api_req_interface_info = *p_intf_cfg;
+
+ BCM_LOG(DEBUG, log_id_interface,
+ " interface object state from API message is: %d, intf_type: %s intf_id: %d\n",
+ p_api_req_interface_info->data.admin_state,
+ interface_type_str_get(p_api_req_interface_info->key.intf_type),
+ p_api_req_interface_info->key.intf_id);
+
+
+ /* SET or GET or ...? */
+ switch (oper_type)
+ {
+
+ case (BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+ BCM_LOG(DEBUG, log_id_interface,
+ "Processing an interface SET REQ mgmt message\n");
+ /*if sched is already set, can not change sched setting using set command, should first delete current sched*/
+ if(BCMBAL_CFG_PROP_IS_SET(p_current_interface_info,interface,ds_tm)
+ && BCMBAL_CFG_PROP_IS_SET(p_api_req_interface_info,interface,ds_tm))
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "ds_tm %d is already set at interface, it should be first cleared in order to be replaced \n",
+ p_current_interface_info->data.ds_tm);
+ ret = BCM_ERR_ALREADY;
+ break;
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(p_current_interface_info,interface,us_tm)
+ && BCMBAL_CFG_PROP_IS_SET(p_api_req_interface_info,interface,us_tm))
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "us_tm %d is already set at interface, it should be first cleared in order to be replaced \n",
+ p_current_interface_info->data.us_tm);
+ ret = BCM_ERR_ALREADY;
+ break;
+ }
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface);
+
+ if(BCM_ERR_OK != ret)
+ {
+ break;
+ }
+
+ /* If this interface is already up, then just return OK */
+ if(BCMBAL_STATE_UP == p_api_req_interface_info->data.admin_state)
+ {
+ if(BCMBAL_STATUS_UP == p_current_interface_info->data.oper_status)
+ {
+ BCM_LOG(DEBUG, log_id_interface,
+ "=====> Received an interface UP for an already UP interface, returning OK\n");
+ break;
+ }
+
+ /*validate and set the interface' tm sched*/
+ bcmbal_interface_object_overlay_w_dst_priority(p_api_req_interface_info,p_current_interface_info);
+ ret = interface_tm_sched_set(p_api_req_interface_info);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface,"Could not set the interface tm sched\n");
+ break;
+ }
+ interface_admin_up_start(&(p_access_terminal_inst->intf_info.interface[interface_index]),
+ msg_payload);
+ }
+ else
+ {
+ if(BCMBAL_STATUS_DOWN == p_current_interface_info->data.oper_status)
+ {
+ BCM_LOG(DEBUG, log_id_interface,
+ "=====> Received an interface DOWN for an already DOWN interface, returning OK\n");
+
+ break;
+ }
+
+ interface_admin_dn_start(&(p_access_terminal_inst->intf_info.interface[interface_index]),
+ msg_payload);
+
+ }
+
+ break;
+
+ }
+ case (BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+
+ BCM_LOG(DEBUG, log_id_interface,
+ "Processing a interface GET REQ mgmt message\n");
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ p_current_interface_info->hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+
+ bcmbal_sub_id_list_u16 sub_term_id_list = {};
+
+ BCMBAL_CFG_PROP_CLEAR(p_current_interface_info,
+ interface,
+ sub_term_id_list);
+
+ /* If the user requested the list of sub_term_ids for this interface,
+ * and this is a PON interface, then return the list.
+ */
+ if(BCMBAL_CFG_PROP_IS_SET(p_api_req_interface_info,
+ interface,
+ sub_term_id_list))
+ {
+ if(BCMBAL_INTF_TYPE_PON == p_current_interface_info->key.intf_type)
+ {
+
+ sub_term_id_list_fill(interface_index, &sub_term_id_list);
+
+ /* NOTE: The returned list may be empty */
+ BCMBAL_CFG_PROP_SET(p_current_interface_info,
+ interface,
+ sub_term_id_list,
+ sub_term_id_list);
+
+ }
+ }
+
+ *((bcmbal_interface_cfg *)msg_payload) = *p_current_interface_info;
+
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface);
+
+ /* Free the temporary list if it was used */
+ if(sub_term_id_list.val)
+ {
+ bcmos_free(sub_term_id_list.val);
+ }
+
+ break;
+ }
+ default:
+ {
+ BCM_LOG(ERROR, log_id_interface,
+ "Unsupported operation on interface object (%d)\n",
+ bcmbal_msg_id_oper_get(msg_payload));
+
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface);
+ break;
+ }
+
+ }
+
+ }while (0);
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function called to initialize a single access-terminal instance.
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @param p_acc_term_inst Pointer to an access terminal instance
+ *
+ * @returns void
+ *****************************************************************************/
+static void initialize_access_terminal_instance_config(acc_term_inst *p_acc_term_inst)
+{
+ int ii;
+ int intf_id;
+ bcmos_errno ret;
+
+ BUG_ON(NULL == p_acc_term_inst);
+
+ p_acc_term_inst->current_acc_term_obj_info.key.access_term_id = 0;
+
+ BCMBAL_CFG_INIT(&p_acc_term_inst->current_acc_term_obj_info,
+ access_terminal,
+ p_acc_term_inst->current_acc_term_obj_info.key);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info,
+ access_terminal,
+ admin_state,
+ BCMBAL_STATE_DOWN);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info,
+ access_terminal,
+ oper_status,
+ BCMBAL_STATUS_DOWN);
+
+ BCMBAL_PROP_SET_PRESENT(&p_acc_term_inst->current_acc_term_obj_info,
+ access_terminal,
+ _cfg,
+ iwf_mode);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_FALSE);
+
+ {
+ bcmbal_interface_key key;
+
+ intf_id = 0; /* reset the port id to the starting id value for the PON interfaces */
+
+ key.intf_type = BCMBAL_INTF_TYPE_PON;
+
+ for(ii=0; ii<NUM_SUPPORTED_SUBSCRIBER_INTERFACES; ii++)
+ {
+
+ key.intf_id = intf_id;
+
+ p_acc_term_inst->intf_info.interface[ii].num_sub_terms_on_int = 0;
+ TAILQ_INIT(&p_acc_term_inst->intf_info.interface[ii].sub_term_id_list);
+
+ BCMBAL_CFG_INIT(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info,
+ interface,
+ key);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info,
+ interface,
+ admin_state,
+ BCMBAL_STATE_DOWN);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info,
+ interface,
+ oper_status,
+ BCMBAL_STATUS_DOWN);
+
+ ret = bcmbal_tm_sched_interface_tm_auto_create(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface, "could not set an auto - create a tm sched for pon if %d", intf_id);
+ break;
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->intf_info.interface[ii].current_int_obj_info), BCMOS_FALSE);
+
+ intf_id++;
+ }
+
+ intf_id = 0; /* reset the port id to the starting id value for the NNI interfaces */
+
+ key.intf_type = BCMBAL_INTF_TYPE_NNI;
+
+ for(ii=NUM_SUPPORTED_SUBSCRIBER_INTERFACES; ii<(NUM_SUPPORTED_SUBSCRIBER_INTERFACES + bal_config_params.num_nni_ports); ii++)
+ {
+
+ key.intf_id = intf_id;
+
+ BCMBAL_CFG_INIT(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info,
+ interface,
+ key);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info,
+ interface,
+ admin_state,
+ BCMBAL_STATE_UP);
+
+ BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info,
+ interface,
+ oper_status,
+ BCMBAL_STATUS_UP);
+
+
+ ret = bcmbal_tm_sched_interface_tm_auto_create(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_interface, "could not set an auto - create a tm sched for nni if %d", intf_id);
+ break;
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->intf_info.interface[ii].current_int_obj_info), BCMOS_FALSE);
+
+ intf_id++;
+ }
+ }
+}
+
+bcmos_errno bcmbal_interface_sub_term_list_entry_add(bcmbal_subscriber_terminal_key sub_term_key)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ acc_term_inst *p_access_terminal_inst;
+ sub_term_id_entry *current_entry;
+ acc_term_interface *p_interface;
+
+ p_access_terminal_inst = access_terminal_get();
+
+ do
+ {
+ /*
+ * If the specified access terminal is not active then it's interfaces are down.
+ */
+ if(NULL == p_access_terminal_inst)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "no such ACTIVE access terminal\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ p_interface = &p_access_terminal_inst->intf_info.interface[sub_term_key.intf_id];
+
+ /* Check if the id is already on the list before adding it */
+ TAILQ_FOREACH(current_entry,
+ &p_interface->sub_term_id_list,
+ next)
+ {
+ if(current_entry->sub_term_id == sub_term_key.sub_term_id)
+ {
+ return BCM_ERR_ALREADY;
+ }
+ }
+
+ /* Get a new entry and configure it */
+ current_entry = bcmos_calloc(sizeof(sub_term_id_entry));
+
+ if (NULL == current_entry)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ current_entry->sub_term_id = sub_term_key.sub_term_id;
+
+ BCM_LOG(INFO, log_id_access_terminal,
+ "adding sub_term id %u to interface %u\n", sub_term_key.sub_term_id, sub_term_key.intf_id);
+
+ /* Save the entry on the list of subscriber-terminal ids on this interface */
+ TAILQ_INSERT_TAIL(&p_interface->sub_term_id_list,
+ current_entry, next);
+
+ (p_interface->num_sub_terms_on_int)++;
+
+ } while (0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_interface_sub_term_list_entry_remove(bcmbal_subscriber_terminal_key sub_term_key)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ acc_term_inst *p_access_terminal_inst;
+ acc_term_interface *p_interface;
+ sub_term_id_entry *current_entry, *p_temp_entry;
+
+ do
+ {
+ p_access_terminal_inst = access_terminal_get();
+
+ /*
+ * If the specified access terminal is not active then it's interfaces are down.
+ */
+ if(NULL == p_access_terminal_inst)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "no such ACTIVE access terminal\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ p_interface = &p_access_terminal_inst->intf_info.interface[sub_term_key.intf_id];
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &p_interface->sub_term_id_list,
+ next,
+ p_temp_entry)
+ {
+ if(current_entry->sub_term_id == sub_term_key.sub_term_id)
+ {
+ /* Remove it from the list of subscriber-terminal ids on this interface */
+ TAILQ_REMOVE(&p_interface->sub_term_id_list,
+ current_entry, next);
+
+ bcmos_free(current_entry);
+
+ (p_interface->num_sub_terms_on_int)--;
+
+ ret = BCM_ERR_OK;
+ break;
+
+ }
+ }
+ } while (0);
+
+ return ret;
+}
+
+static bcmos_errno sub_term_id_list_fill(uint32_t interface_index,
+ bcmbal_sub_id_list_u16 *sub_term_id_list)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ acc_term_inst *p_acc_term_inst;
+ sub_term_id_entry *current_entry = NULL;
+ int ii = 0;
+
+ do
+ {
+ /*
+ * See if the access-terminal is active
+ */
+ p_acc_term_inst = access_terminal_get();
+
+ /*
+ * If the specified access terminal is not active then it's interfaces are down.
+ */
+ if(NULL == p_acc_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "no such ACTIVE access terminal\n");
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* Traverse the list of sub_term_ids recorded and fill in the list to be returned */
+ sub_term_id_list->len = p_acc_term_inst->intf_info.interface[interface_index].num_sub_terms_on_int;
+ sub_term_id_list->val = bcmos_calloc(sizeof(bcmbal_sub_id) * sub_term_id_list->len);
+
+ if (NULL == sub_term_id_list->val)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ TAILQ_FOREACH(current_entry,
+ &p_acc_term_inst->intf_info.interface[interface_index].sub_term_id_list,
+ next)
+ {
+ BCM_LOG(DEBUG, log_id_access_terminal,
+ "adding sub_term_id %u to response at array location %u\n",
+ current_entry->sub_term_id,
+ ii);
+ sub_term_id_list->val[ii++] = current_entry->sub_term_id;
+ }
+
+ } while (0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_interface_tm_get(bcmbal_interface_key key, bcmbal_tm_sched_id *id)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ acc_term_inst *p_acc_term_inst;
+ uint32_t interface_index = INVALID_INTERFACE_INDEX;
+
+ do
+ {
+ /* See if the access-terminal is active */
+ p_acc_term_inst = access_terminal_get();
+
+ /* If the specified access terminal is not active then it's interfaces are down. */
+ if(NULL == p_acc_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,"no such ACTIVE access terminal\n");
+ ret = BCM_ERR_NOT_CONNECTED;
+ break;
+ }
+
+ /* If the specified access terminal is down, then it's interfaces are down. */
+ if(BCMBAL_STATE_UP != p_acc_term_inst->current_acc_term_obj_info.data.admin_state)
+ {
+ ret = BCM_ERR_NOT_CONNECTED;
+ break;
+ }
+
+ /* first get the index to the interface array from port id/type */
+ interface_index = bcmbal_port_type_and_id_to_interface_index (key.intf_type, key.intf_id);
+ if (interface_index >= INVALID_INTERFACE_INDEX)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,"INVALID port type/id (%s/%d) to interface index (%d)\n",
+ interface_type_str_get(key.intf_type), key.intf_id, interface_index);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* Retrieve the relevany default tm sched of the interface */
+ if (BCMBAL_INTF_TYPE_NNI == key.intf_type)
+ {
+ *id = p_acc_term_inst->intf_info.interface[interface_index].current_int_obj_info.data.us_tm;
+ }
+ else /*BCMBAL_INTF_TYPE_PON */
+ {
+ *id = p_acc_term_inst->intf_info.interface[interface_index].current_int_obj_info.data.ds_tm;
+ }
+ }while(0);
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function that returns the status of the specified interface object
+ *
+ * @param key An interface instance key
+ *
+ * @returns bcmbal_state
+ *****************************************************************************/
+bcmbal_status bcmbal_interface_status_get(bcmbal_interface_key key)
+{
+ bcmbal_state intf_status = BCMBAL_STATUS_DOWN;
+ acc_term_interface *p_acc_term_interface = bcmbal_interface_get(key);
+
+ if(NULL == p_acc_term_interface)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,"no such interface\n");
+ }
+ else
+ {
+ intf_status = p_acc_term_interface->current_int_obj_info.data.oper_status;
+ }
+ return intf_status;
+}
+/*****************************************************************************/
+/**
+ * @brief A function that returns the interface object
+ *
+ * @param key An interface instance key
+ *
+ * @returns acc_term_interface *p_acc_term_interface a pointer to the interface object
+ *****************************************************************************/
+static acc_term_interface * bcmbal_interface_get(bcmbal_interface_key key)
+{
+ acc_term_inst *p_acc_term_inst = NULL;
+ acc_term_interface *p_acc_term_interface = NULL;
+ uint32_t interface_index = INVALID_INTERFACE_INDEX;
+
+ do
+ {
+ /*
+ * See if the access-terminal is active
+ */
+ p_acc_term_inst = access_terminal_get();
+
+
+ /*
+ * If the specified access terminal is not active then it's interfaces are down.
+ */
+ if(NULL == p_acc_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "no such ACTIVE access terminal\n");
+ break;
+ }
+
+ /*
+ * Retrieve the interface
+ */
+ /* first get the index to the interface array from port id/type */
+ interface_index = bcmbal_port_type_and_id_to_interface_index (key.intf_type, key.intf_id);
+ if (interface_index >= INVALID_INTERFACE_INDEX)
+ {
+ BCM_LOG(ERROR, log_id_access_terminal,
+ "INVALID port type/id (%s/%d) to interface index (%d)\n",
+ interface_type_str_get(key.intf_type), key.intf_id, interface_index);
+ break;
+ }
+ p_acc_term_interface = &(p_acc_term_inst->intf_info.interface[interface_index]);
+
+ }while(0);
+
+
+ return p_acc_term_interface;
+}
+
+static char *interface_type_str_get(bcmbal_intf_type intf_type)
+{
+ return intf_type == BCMBAL_INTF_TYPE_NNI ? "NNI" :
+ intf_type == BCMBAL_INTF_TYPE_PON ? "PON" : "UNKNOWN TYPE";
+}
+/*@}*/
diff --git a/bal_release/src/core/main/acc_term_fsm.h b/bal_release/src/core/main/acc_term_fsm.h
new file mode 100644
index 0000000..c2337ae
--- /dev/null
+++ b/bal_release/src/core/main/acc_term_fsm.h
@@ -0,0 +1,199 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file acc_term_fsm.h
+ * @brief Code to support the BAL Access Terminal FSM
+ *
+ * @defgroup access_terminal Access Terminal
+ * @ingroup core
+ */
+
+
+#ifndef ACC_TERM_FSM_H
+#define ACC_TERM_FSM_H
+
+/*@{*/
+
+#include <bcm_topo.h>
+#include <bal_api.h>
+#include <sub_term_fsm.h>
+#include <tm_sched_fsm.h>
+
+
+/** An enumeration of the access-terminal FSM events.
+ */
+typedef enum
+{
+ ACC_TERM_FSM_EVENT_TYPE_NONE = -1,
+ ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP ,
+ ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN ,
+ ACC_TERM_FSM_EVENT_TYPE_INT_ADMIN_UP ,
+ ACC_TERM_FSM_EVENT_TYPE_INT_ADMIN_DN ,
+ ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG ,
+ ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG ,
+ ACC_TERM_FSM_EVENT_TYPE_TIMEOUT ,
+
+
+ ACC_TERM_FSM_EVENT_TYPE__LAST,
+ ACC_TERM_FSM_EVENT_TYPE__NUM_OF
+} acc_term_fsm_event_type;
+
+
+/** An enumeration of the access-terminal FSM states.
+ */
+typedef enum
+{
+ ACC_TERM_FSM_STATE_NONE = -1,
+ ACC_TERM_FSM_STATE_NULL ,
+ ACC_TERM_FSM_STATE_ADDING ,
+ ACC_TERM_FSM_STATE_ADDED ,
+ ACC_TERM_FSM_STATE_REMOVING ,
+
+ ACC_TERM_FSM_STATE__LAST,
+ ACC_TERM_FSM_STATE__NUM_OF
+} acc_term_fsm_state;
+
+/**
+ * A structure that defines the information associated with an
+ * access-terminal FSM event
+ */
+typedef struct acc_term_fsm_event
+{
+ acc_term_fsm_event_type event_type; /**< An FSM event */
+ void *msg; /**< A pointer to the message being processed by the FSM during an event */
+} acc_term_fsm_event;
+
+/**
+ * @brief A temporary set of definitions to support access-terminal interfaces.
+ * This should be replaced by a more generic mapping method.
+ * @note The max PON interface of 16 is a practical limit that access term will support for now.
+ */
+#define NUM_SUPPORTED_SUBSCRIBER_INTERFACES (16)
+#define NUM_SUPPORTED_NNI_INTERFACES (BCM_TOPO_MAX_NNI_PORTS)
+#define NUM_SUPPORTED_INTERFACES (NUM_SUPPORTED_SUBSCRIBER_INTERFACES + NUM_SUPPORTED_NNI_INTERFACES)
+/** invalid interface index - used for any error in mapping port type/id to interface index */
+#define INVALID_INTERFACE_INDEX (NUM_SUPPORTED_INTERFACES)
+
+#define BAL_ACC_TERM_MAX_FLOWS_PER_PON (1024)
+#define BAL_ACC_TERM_MAX_FLOWS (NUM_SUPPORTED_SUBSCRIBER_INTERFACES * BAL_ACC_TERM_MAX_FLOWS_PER_PON)
+
+typedef struct sub_term_id_entry
+{
+ bcmbal_sub_id sub_term_id;
+ TAILQ_ENTRY(sub_term_id_entry) next; /**< TAILQ link */
+}sub_term_id_entry;
+
+/**
+ * Two interface objects associated with the access-terminal.
+ * One stores the API requests, and one records the current
+ * state of the object.
+ */
+typedef struct acc_term_interface
+{
+ bcmbal_interface_cfg current_int_obj_info; /**< The current information for this interface (used for GET) */
+ bcmbal_interface_cfg api_req_int_obj_info; /**< The last interface object info received from the Public API */
+ uint16_t num_sub_terms_on_int; /**< The number of subscriber terminals on this interface */
+ TAILQ_HEAD(sub_term_id_list_head, sub_term_id_entry) sub_term_id_list;
+} acc_term_interface;
+
+/**
+ * The interface key of the instance being manipulated, and an array of interface objects associated
+ * with an access terminal instance.
+ */
+typedef struct acc_term_interface_info
+{
+ acc_term_interface interface[NUM_SUPPORTED_INTERFACES]; /**< All interface instances */
+
+}acc_term_interface_info;
+
+
+/**
+ * An structure defining an access terminal instance and its associated interfaces
+ */
+typedef struct acc_term_inst
+{
+ /**< The current information for this access-terminal (used for GET) */
+ bcmbal_access_terminal_cfg current_acc_term_obj_info;
+
+ /**< The last access-terminal object info received from the Public API */
+ bcmbal_access_terminal_cfg api_req_acc_term_obj_info;
+
+ acc_term_fsm_state fsm_state; /**< The access-terminal FSM state */
+ acc_term_interface_info intf_info; /**< The access-terminal interfaces */
+ bcmos_timer timer_info; /**< A structure used for the state machine timeout timer */
+
+} acc_term_inst;
+
+
+/*--- external function declarations ---*/
+extern bcmos_errno process_access_terminal_object(void *msg_payload);
+
+extern bcmos_errno process_access_terminal_util_msg(void *msg_payload);
+
+extern bcmos_errno process_interface_object(void *msg_payload);
+
+extern bcmos_errno process_interface_util_msg(void *msg_payload);
+
+extern bcmos_errno bcmbal_interface_sub_term_list_add(bcmbal_subscriber_terminal_key sub_term_key);
+
+extern bcmos_errno bcmbal_interface_sub_term_list_remove(bcmbal_subscriber_terminal_key sub_term_key);
+
+extern void access_terminal_fsm_init(void);
+
+extern bcmbal_status bcmbal_interface_status_get(bcmbal_interface_key key);
+
+extern bcmbal_status bcmbal_get_intf_oper_status_from_admin_state (bcmbal_state intf_admin_state);
+
+extern uint32_t bcmbal_port_type_and_id_to_interface_index(bcmbal_intf_type intf_type,
+ bcmbal_intf_id intf_id);
+extern bcmbal_status acc_term_status_get(void);
+
+extern bcmos_errno bcmbal_interface_sub_term_list_entry_add(bcmbal_subscriber_terminal_key sub_term_key);
+
+extern bcmos_errno bcmbal_interface_sub_term_list_entry_remove(bcmbal_subscriber_terminal_key sub_term_key);
+
+extern bcmos_errno bcmbal_interface_tm_get(bcmbal_interface_key key, bcmbal_tm_sched_id *id);
+
+extern bcmos_errno interface_tm_sched_unset(bcmbal_interface_key intf_key, bcmbal_tm_sched_key sched_key);
+
+extern bcmos_errno bcmbal_tm_sched_interface_tm_auto_create(bcmbal_interface_cfg *p_interface_info);
+
+extern bcmos_errno bcmbal_tm_sched_set_interface_owner(bcmbal_interface_key interface_key, tm_sched_inst *p_tm_sched_inst);
+
+extern bcmos_errno bcmbal_tm_sched_set_sub_term_owner( bcmbal_tm_sched_key tm_sched_key, const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg);
+
+
+/*@}*/
+
+#endif /*ACC_TERM_FSM_H */
+
+
diff --git a/bal_release/src/core/main/bal_cli.c b/bal_release/src/core/main/bal_cli.c
new file mode 100644
index 0000000..cd2c389
--- /dev/null
+++ b/bal_release/src/core/main/bal_cli.c
@@ -0,0 +1,423 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_cli.c
+ * @brief Sample CLI which is used to exercise the BAL Public API
+ *
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+
+#include <bal_common.h>
+
+#include <bal_core.h>
+#include <bal_api.h>
+#include <bal_api_cli.h>
+#include <bcmos_cli.h>
+#include <rsc_mgr_cli.h>
+#include <bal_switch_acc_term.h>
+#include <bal_mac_util.h>
+#include <bal_switch_util.h>
+#include "bal_cli.h"
+
+#ifdef OMCI_SVC
+#include <omci_svc.h>
+#include <omci_svc_cli.h>
+#endif
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+/*
+ * CLI logging device ids
+ */
+dev_log_id log_id_cli;
+
+/* CLI logging for ONU discovery */
+dev_log_id log_id_cli_disc;
+#endif
+bcmcli_session *current_session;
+
+/* user_exit_cb is only supported when BAL is built with a user application
+ * and run as a set of threads in that application (i.e. when bcmbal_init is
+ * called) */
+static bcmbal_exit_cb user_exit_cb;
+static bcmos_task bal_cli_thread;
+
+static const char *bal_iwf_mode_to_str(bcmbal_iwf_mode iwf_mode)
+{
+ static const char *str_table[BCMBAL_IWF_MODE__NUM_OF] =
+ {
+ [BCMBAL_IWF_MODE_DIRECT_MAPPING] = "direct_mapping",
+ [BCMBAL_IWF_MODE_PER_FLOW] = "per_flow",
+ };
+ return (iwf_mode >= BCMBAL_IWF_MODE__NUM_OF) ? "<unknown>" : str_table[iwf_mode];
+}
+
+static const char *bal_intf_maptable_to_str(bal_swapp_port_map_indx intf_maptable)
+{
+ static const char *str_table[BAL_SWAPP_PORT_MAP__NUM_OF] =
+ {
+ [BAL_SWAPP_PORT_MAP_GPON] = "gpon",
+ [BAL_SWAPP_PORT_MAP_GPON_V3] = "gpon v3",
+ [BAL_SWAPP_PORT_MAP_EXP] = "exp",
+ [BAL_SWAPP_PORT_MAP_EXP2] = "exp 2",
+ [BAL_SWAPP_PORT_MAP_SVK4] = "svk4",
+ [BAL_SWAPP_PORT_MAP_EPON_TDMA] = "epon_tdma",
+ [BAL_SWAPP_PORT_MAP_EPON_1G] = "epon_1g",
+ [BAL_SWAPP_PORT_MAP_EPON_10G] = "epon_10g",
+ };
+ return (intf_maptable >= BAL_SWAPP_PORT_MAP__NUM_OF) ? "<unknown>" : str_table[intf_maptable];
+}
+
+/*
+ * show_confif CLI command handler
+ */
+static bcmos_errno bal_show_config_cmd(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ const bcmbal_config_params *bal_config = bcmbal_config_get();
+ bcmolt_devid device_id;
+
+ bcmcli_session_print(session, "interworking mode is : %s\n", bal_iwf_mode_to_str(bal_config->iwf_mode));
+ bcmcli_session_print(session, "switch interface mapping table is : %s\n", bal_intf_maptable_to_str(bal_config->intf_maptable));
+ bcmcli_session_print(session, "mac is %s loopback mode \n", bcmbal_is_mac_in_loopback() ? "IN" : "NOT IN");
+ bcmcli_session_print(session, "number of nni ports is : %d \n", bal_config->num_nni_ports);
+ bcmcli_session_print(session, "port for trapped packets is : %d \n", bal_config->trap_udp_port);
+
+ BCM_TOPO_FOR_EACH_DEV(device_id)
+ {
+ bcmcli_session_print(session, "pon mode of device %d is %s , number of pons is %d\n", device_id,
+ bcm_topo_dev_get_pon_mode_str(device_id),bcm_topo_dev_get_max_pon(device_id));
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* "quit" CLI command handler */
+static int _cmd_quit(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bcmcli_stop(sess);
+ bcmcli_session_print(sess, "BAL core CLI terminated by 'Quit' command\n");
+ return 0;
+}
+
+/* "sleep" CLI command handler */
+static bcmos_errno _cmd_sleep(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bcmos_usleep(parm[0].value.unumber);
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the BAL core debug CLI
+ *
+ * @returns BCM_ERR_OK
+ *
+ *****************************************************************************/
+static bcmos_errno bal_debug_init(void)
+{
+ bcmcli_entry *dir;
+
+ dir = bcmcli_dir_add(NULL, "debug", "BAL core debug CLI", BCMCLI_ACCESS_ADMIN, NULL);
+
+ /* Add the resource manager debug CLI */
+ rsc_mgr_cli_init(dir);
+ mac_util_cli_init(dir);
+
+ /* Add the switch util debug CLI */
+ sw_util_cli_init(dir);
+
+#ifdef OMCI_SVC
+ if (!omci_svc_is_loopback())
+ omci_svc_cli_init(dir);
+#endif
+
+ BCMCLI_MAKE_CMD(dir, "sleep", "Sleep for a specified number of usec", _cmd_sleep,
+ BCMCLI_MAKE_PARM("time to sleep (microseconds)", "time to sleep (microseconds)", BCMCLI_PARM_UDECIMAL, 0));
+
+ BCMCLI_MAKE_CMD_NOPARM(dir, "show_config", "show bal configuration", bal_show_config_cmd);
+
+ /* Add os CLI */
+ bcmos_cli_init(dir);
+
+ return BCM_ERR_OK;
+}
+
+/** BAL Indication callback handler */
+static void api_ind_cb_handler(bcmbal_obj *obj)
+{
+
+ if((BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL == obj->obj_type) &&
+ (BCMBAL_SUB_ID_UNKNOWN == ((bcmbal_subscriber_terminal_cfg *)obj)->key.sub_term_id))
+ {
+ bcmbal_serial_number *p_serial_number =
+ &(((bcmbal_subscriber_terminal_cfg *)obj)->data.serial_number);
+
+ BCM_LOG(DEBUG, log_id_cli_disc, "Discovered ONU serial number "
+ "%2X%2X%2X%2X%1X%1X%1X%1X%1X%1X%1X%1X "
+ "on PON %d\n",
+ p_serial_number->vendor_id[0],
+ p_serial_number->vendor_id[1],
+ p_serial_number->vendor_id[2],
+ p_serial_number->vendor_id[3],
+ p_serial_number->vendor_specific[0]>>4 & 0x0f,
+ p_serial_number->vendor_specific[0] & 0x0f,
+ p_serial_number->vendor_specific[1]>>4 & 0x0f,
+ p_serial_number->vendor_specific[1] & 0x0f,
+ p_serial_number->vendor_specific[2]>>4 & 0x0f,
+ p_serial_number->vendor_specific[2] & 0x0f,
+ p_serial_number->vendor_specific[3]>>4 & 0x0f,
+ p_serial_number->vendor_specific[3] & 0x0f,
+
+ ((bcmbal_subscriber_terminal_cfg *)obj)->key.intf_id);
+ }
+ else
+ {
+ char obj_key_str[256];
+
+ bal_obj_key_str_get(obj, obj_key_str);
+
+ BCM_LOG(INFO, log_id_cli,
+ "Processing CLI API \'%s\' IND callback (status is %s), (key is %s)\n",
+ bcmbal_objtype_str(obj->obj_type),
+ bcmos_strerror(obj->status),
+ obj_key_str);
+ }
+
+ return;
+}
+
+/* Execute CLI script */
+bcmos_errno bcmbal_cli_exec_script(const char *filename)
+{
+ char buf[1024];
+ FILE *f;
+
+ f = fopen(filename, "r");
+ if (!f)
+ {
+ printf("Can't open file %s for reading\n", filename);
+ return BCM_ERR_PARM;
+ }
+ while (!bcmcli_is_stopped(current_session) && !feof(f) &&
+ fgets(buf, sizeof(buf)-1, f))
+ {
+ bcmcli_print(current_session, "%s", buf);
+ bcmcli_parse(current_session, buf);
+ }
+ fclose(f);
+ return BCM_ERR_OK;
+}
+
+/* Execute init CLI script if any */
+bcmos_errno bcmbal_cli_exec_init_script(void)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ const char *init_script = bcmbal_config_get()->init_script;
+
+ if (init_script)
+ ret = bcmbal_cli_exec_script(init_script);
+
+ return ret;
+}
+
+/* CLI thread handler */
+static int _bal_cli_thread_handler(long data)
+{
+ char init_string[]="\n";
+ bcmcli_session *sess = current_session;
+
+ /* 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);
+ };
+ BCM_LOG(INFO, log_id_core, "BAL CLI terminated\n");
+
+ /* call the user's exit callback, if any */
+ if(user_exit_cb) (*user_exit_cb)();
+
+ current_session = NULL;
+ bcmcli_session_close(sess);
+
+ return 0;
+}
+
+/*****************************************************************************/
+/**
+ * @brief This function initializes the BAL CLI
+ *
+ * @returns BCM_ERR_OK on success, other bcmos_errno codes otherwise
+ *
+ *****************************************************************************/
+bcmos_errno bcmbal_cli_init(bcmbal_exit_cb exit_cb)
+{
+ const bcmbal_config_params *bal_config = bcmbal_config_get();
+ bcmcli_session_parm mon_session_parm = {};
+ bcmos_task_parm bal_cli_task_p = {};
+ bcmcli_entry *dir;
+ bcmos_errno ret;
+ bcmbal_cb_cfg cb_cfg = {};
+
+ mon_session_parm.access_right = bal_config->access;
+ mon_session_parm.line_edit_mode = bal_config->edit_mode;
+
+#ifdef ENABLE_LOG
+ /*
+ * Initialize the logging context
+ */
+ log_id_cli = bcm_dev_log_id_register("CLI", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_cli == DEV_LOG_INVALID_ID);
+
+ log_id_cli_disc = bcm_dev_log_id_register("CLI_DISC", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_cli_disc == DEV_LOG_INVALID_ID);
+#endif
+
+ do
+ {
+ ret = bcmcli_session_open(&mon_session_parm, ¤t_session);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_cli, "Can't open CLI session\n");
+ break;
+ }
+
+ {
+ cb_cfg.obj_type = BCMBAL_OBJ_ID_ANY;
+ cb_cfg.ind_cb_hdlr = (f_bcmbal_ind_handler )api_ind_cb_handler;
+
+ bcmbal_subscribe_ind(&cb_cfg);
+ }
+
+ /* Initialize the bal api cli UI */
+ if(NULL == (dir = bcmcli_dir_add(NULL, "bal", "BAL API access", BCMCLI_ACCESS_ADMIN, NULL)))
+ {
+ BCM_LOG(ERROR, log_id_cli, "Could not initialize the BAL API CLI hierarchy\n");
+ break;
+ }
+
+ ret = bcmbal_apicli_add_commands(current_session, dir);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_cli, "Could not initialize the BAL CLI: %s\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /* Initialize the bal "debug" CLI */
+ ret = bal_debug_init();
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Error initializing the bal debug cli\n");
+ break;
+ }
+
+#ifdef ENABLE_LOG
+ /* Add logger CLI */
+ bcm_dev_log_cli_init(NULL);
+#endif
+
+ /* Add "quit" command at the top level */
+ BCMCLI_MAKE_CMD_NOPARM(NULL, "quit", "Quit", _cmd_quit);
+
+
+ /* Record the user's choice of callback function on our exit (may be NULL!) */
+ user_exit_cb = exit_cb;
+
+ /* Create BAL CLI thread */
+ bal_cli_task_p.name = "bal_cli_thread";
+ bal_cli_task_p.handler = _bal_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 CLI thread\n");
+ return ret;
+ }
+
+ } while(0);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief This function un-initializes the BAL CLI
+ *
+ * @returns BCM_ERR_OK
+ *
+ *****************************************************************************/
+bcmos_errno bcmbal_cli_finish(void)
+{
+ if (!current_session)
+ return BCM_ERR_OK;
+
+ bcmbal_cli_stop();
+
+ bcmos_task_destroy(&bal_cli_thread);
+
+ bcmbal_api_finish();
+
+ return BCM_ERR_OK;
+}
+
+
+/* Stop CLI */
+void bcmbal_cli_stop(void)
+{
+ if (current_session)
+ {
+ bcmcli_stop(current_session);
+ while (current_session)
+ bcmos_usleep(10000);
+ }
+}
+
+/* Is CLI terminated? */
+bcmos_bool bcmbal_cli_is_terminated(void)
+{
+ return (current_session == NULL) || bcmcli_is_stopped(current_session);
+}
+
+/*@}*/
diff --git a/bal_release/src/core/main/bal_cli.h b/bal_release/src/core/main/bal_cli.h
new file mode 100644
index 0000000..c4f19b6
--- /dev/null
+++ b/bal_release/src/core/main/bal_cli.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_cli.h
+ * @brief All functions and definitions supplied by the Sample CLI
+ *
+ */
+
+
+#ifndef BAL_CLI_H
+#define BAL_CLI_H
+
+#include <bcmcli.h>
+#include <bcmos_cli.h>
+#include <bal_core.h>
+/*@{*/
+
+extern bcmos_errno bcmbal_cli_init(bcmbal_exit_cb exit_cb);
+extern void bcmbal_cli_stop(void);
+extern bcmos_errno bcmbal_cli_finish(void);
+extern bcmos_errno bcmbal_cli_exec_init_script(void);
+extern bcmos_errno bcmbal_cli_exec_script(const char *filename);
+extern bcmos_bool bcmbal_cli_is_terminated(void);
+extern bcmcli_session *current_session;
+
+
+/*@}*/
+
+#endif /* BAL_CLI_H */
+
diff --git a/bal_release/src/core/main/bal_core.c b/bal_release/src/core/main/bal_core.c
new file mode 100644
index 0000000..fcc1573
--- /dev/null
+++ b/bal_release/src/core/main/bal_core.c
@@ -0,0 +1,1018 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_core.c
+ * @brief The code that comprises the main entry point and initialization
+ * code for the BAL Core.
+ *
+ * @addtogroup ctrlr
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bcmcli.h>
+#include <bal_switch_util.h>
+#include <bal_mac_util.h>
+#include <bal_version.h>
+#include <cmdline.h>
+#include <bal_core.h>
+#include <bal_cli.h>
+
+#include "rsc_mgr.h"
+#include "bal_worker.h"
+#include "bal_switch_acc_term.h"
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+#endif
+
+#ifdef OMCI_SVC
+#include <omci_svc.h>
+#endif
+
+#if defined(CONFIG_MAC_RPC)
+#define CONFIG_MAC_UTIL_IP_PORT
+#endif
+
+#ifdef ENABLE_LOG
+/*
+ * @brief The Logging device id for the BAL core
+ */
+dev_log_id log_id_core;
+#endif
+
+
+/*--- local function declarations ---*/
+static void welcome_to_bal(void);
+static bcmos_errno bal_core_init(void);
+static void bal_core_finish(void);
+static void bal_parse_config(struct bcmbal_config_params *p_params);
+static bcmos_errno bal_rpc_soc_gen(void);
+
+/*
+ * Worker thread and RX thread(s) data structures
+ */
+static bcmos_task core_worker_thread;
+
+static bcmos_errno _usage(const char *cmd);
+
+#define BAL_CHECK_IP_ARGUMENT(_i, _argc, _option) \
+ do { \
+ if (_i == _argc - 1) \
+ { \
+ printf("Error: IP:port is expected after %s option\n", _option); \
+ return _usage(argv[0]);\
+ }\
+ } while (0)
+
+
+#define CORE_MGMT_IP_PORT_CMDLINE_OPT "-C"
+#define BAL_API_IP_PORT_CMDLINE_OPT "-A"
+#define BAL_MAC_IP_PORT_CMDLINE_OPT "-M"
+#define BAL_SW_IP_CMDLINE_OPT "-S"
+#define BAL_INIT_SCRIPT_OPT "-f"
+#define BAL_LOG_FILE_OPT "-F"
+#define BAL_HELP_OPT "-h"
+#define BAL_LONG_HELP_OPT "--help"
+#define BAL_LEVEL_OPT "-L"
+#define BAL_NO_LOG_OPT "-nl"
+#define BAL_LOG_SYSLOG_OPT "-syslog"
+#define BAL_NO_LINEEDIT_OPT "-ne"
+
+
+/* Command line arguments */
+static cl_argument supported_cl_args[] =
+{
+#ifdef CONFIG_MAC_UTIL_IP_PORT
+ { .short_name = BAL_MAC_IP_PORT_CMDLINE_OPT,
+ .extra_arg = "mac_device_ip:port",
+ .description = "IP address:UDP port where the MAC device listens for RPC messages",
+ .flags = CL_ARGUMENT_FLAG_MANDATORY,
+ .owner = "BAL"
+ },
+#endif
+#ifdef CONFIG_SWITCH_RPC
+ { .short_name = BAL_SW_IP_CMDLINE_OPT,
+ .extra_arg = "switch_ip",
+ .description = "Switch IP address for RPC messages",
+ .flags = CL_ARGUMENT_FLAG_MANDATORY,
+ },
+#endif
+ { .short_name = CORE_MGMT_IP_PORT_CMDLINE_OPT,
+ .extra_arg = "core_mgmt_ip:port",
+ .description = "IP address:UDP port where the core listens for messages from the BAL Public API",
+ },
+ { .short_name = BAL_API_IP_PORT_CMDLINE_OPT,
+ .extra_arg = "al_api_mgmt ip:port",
+ .description = "IP address:UDP port where BAL Public API listens for responses from the core",
+ },
+ { .short_name = BAL_LEVEL_OPT,
+ .extra_arg = "level",
+ .description = "CLI level: guest | admin | debug",
+ },
+ { .short_name = BAL_NO_LINEEDIT_OPT,
+ .description = "Disable line editing",
+ },
+ { .short_name = BAL_INIT_SCRIPT_OPT,
+ .extra_arg = "script_file_name",
+ .description = "Script containing BAL CLI commands",
+ },
+#ifdef ENABLE_LOG
+ { .short_name = BAL_LOG_FILE_OPT,
+ .extra_arg = "log_file_name",
+ .description = "Log into file",
+ },
+ { .long_name = BAL_LOG_SYSLOG_OPT,
+ .description = "Log to syslog",
+ },
+ { .short_name = BAL_NO_LOG_OPT,
+ .description = "Disable logger",
+ },
+#endif
+#ifndef BUILD_OF_AGENT
+ { .short_name = BAL_HELP_OPT,
+ .long_name = BAL_LONG_HELP_OPT,
+ .description = "This help",
+ },
+#endif
+};
+
+/*
+ * The BAL core config file definitions
+ */
+
+#define TOPOLOGY_FILE_NAME "bal_topology.ini"
+#define CONFIG_FILE_NAME "bal_config.ini"
+#define MAX_CONFIG_FILE_LINE_LEN 256
+#define MAX_CONFIG_PARAM_NAME_LEN 64
+#define MAX_CONFIG_PARAM_VALUE_LEN 64
+
+bcmbal_config_params bal_config_params =
+{
+ .iwf_mode = BCMBAL_IWF_MODE_PER_FLOW,
+ .intf_maptable = 2,
+ .num_nni_ports = BCM_TOPO_MAX_NNI_PORTS,
+ /* The interface mapping table default value is set in the switch utilities */
+ .topo_params.pon_mode = BCM_TOPO_PON_MODE_INVALID,
+ /* Default CLI session parameters */
+ .access = BCMCLI_ACCESS_ADMIN,
+ .edit_mode = BCMCLI_LINE_EDIT_DEFAULT,
+};
+static bcmos_bool bal_initialized;
+
+#define RPC_SOC_TEMPLATE_FILE_NAME "rpc.soc.template"
+#define RPC_SOC_FILE_NAME "rpc.soc"
+#define MAX_CMD_LINE_LEN 256
+
+ /*
+ * An enumeration of the possible iwf modes
+ */
+static bcmcli_enum_val iwf_mode_enum[] = {
+ { .name="direct", .val=BCMBAL_IWF_MODE_DIRECT_MAPPING},
+ { .name="per_flow", .val=BCMBAL_IWF_MODE_PER_FLOW},
+ BCMCLI_ENUM_LAST
+};
+
+/**
+ * @brief The Broadcom Ltd logo.
+ */
+static const char *g_p_company_logo =
+"\n\n"
+" *\n"
+" * *\n"
+" * *\n"
+" * *\n"
+" * *\n"
+" * *\n"
+" * *\n"
+" * * * * * *\n"
+" * * * *\n\n"
+"Copyright (c) 2017 Broadcom Ltd\n\n";
+
+
+#ifdef ENABLE_LOG
+/* Create log_id for the core */
+static void bal_core_log_init(void)
+{
+ /* Register the core logging context */
+ log_id_core = bcm_dev_log_id_register("CORE_CTRLR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_core == DEV_LOG_INVALID_ID);
+
+ bcm_dev_log_level_set_style(DEV_LOG_LEVEL_FATAL, BCM_DEV_LOG_STYLE_BOLD);
+ bcm_dev_log_level_set_style(DEV_LOG_LEVEL_ERROR, BCM_DEV_LOG_STYLE_BOLD);
+
+ BCM_LOG(DEBUG, log_id_core, "BAL Core is starting\n");
+}
+
+/* Initialize logger */
+static int bal_dev_log_time_to_str_cb(uint32_t bal_time, char *time_str, int time_str_size)
+{
+ /* Round timestamp to the nearest ms */
+ uint32_t time_ms = (bal_time + 500) / 1000;
+ return snprintf(time_str, time_str_size, "%05u.%03u", time_ms / 1000, time_ms % 1000);
+}
+#endif
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the system logging subsystem
+ *
+ * This function is executed at system startup time
+ *
+ *****************************************************************************/
+bcmos_errno bcmbal_log_init(void)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifdef ENABLE_LOG
+ const char *log_file_name = bal_config_params.log_file_name;
+ if (bal_config_params.disable_log)
+ return BCM_ERR_OK;
+ do
+ {
+ if (NULL == log_file_name && !bal_config_params.log_syslog)
+ {
+#define DEV_LOG_SIZE1 1<<20
+#define DEV_LOG_QUEUE_SIZE 1000
+ static uint8_t logger_buf1[DEV_LOG_SIZE1];
+ void *addresses[DEV_LOG_MAX_FILES] = {logger_buf1};
+ uint32_t sizes[DEV_LOG_MAX_FILES] = {sizeof(logger_buf1)};
+ uint32_t flags[DEV_LOG_MAX_FILES] = {BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND};
+ /* Initialize the system logger for the core threads */
+ ret = bcm_dev_log_init_default_logger(addresses,
+ sizes,
+ flags,
+ BCM_SIZEOFARRAY(addresses),
+ 0x4000,
+ TASK_PRIORITY_DEV_LOG,
+ DEV_LOG_QUEUE_SIZE);
+ }
+ else
+ {
+ bcm_dev_log_parm dev_log_parm = {};
+ int nfiles = 0;
+ if (NULL != log_file_name)
+ {
+ dev_log_parm.log_file[nfiles].type = BCM_DEV_LOG_FILE_REGULAR;
+ dev_log_parm.log_file[nfiles].udef_parms = (char *)(long)log_file_name;
+ dev_log_parm.log_file[nfiles].flags = BCM_DEV_LOG_FILE_FLAG_VALID;
+ ++nfiles;
+ };
+ if (bal_config_params.log_syslog)
+ {
+ dev_log_parm.log_file[nfiles].type = BCM_DEV_LOG_FILE_SYSLOG;
+ dev_log_parm.log_file[nfiles].udef_parms = "BAL";
+ dev_log_parm.log_file[nfiles].flags = BCM_DEV_LOG_FILE_FLAG_VALID;
+ ++nfiles;
+ };
+ ret = bcm_dev_log_init_default_logger_ext(&dev_log_parm,
+ nfiles, /* Log into file and/or syslog */
+ 0x4000,
+ TASK_PRIORITY_DEV_LOG,
+ DEV_LOG_QUEUE_SIZE);
+ }
+
+ if(BCM_ERR_OK != ret)
+ {
+ printf("Error initializing logger default values (%s)\n", bcmos_strerror(ret));
+ break;
+ }
+
+ bcm_dev_log_set_time_to_str_cb(bal_dev_log_time_to_str_cb);
+ }
+ while(0);
+#endif /* #ifdef ENABLE_LOG */
+
+ return ret;
+}
+
+
+/* Parse command line parameters */
+bcmos_errno bcmbal_cmdline_parse(int argc, char *argv[])
+{
+ int i;
+
+ if (cl_validate(argc, argv, supported_cl_args, BCM_SIZEOFARRAY(supported_cl_args)) != BCM_ERR_OK)
+ return _usage(argv[0]);
+
+ /*
+ * Parse all optional arguments
+ */
+ for (i = 1; i < argc; i++)
+ {
+ if (!strcmp(argv[i], CORE_MGMT_IP_PORT_CMDLINE_OPT))
+ {
+ BAL_CHECK_IP_ARGUMENT(i, argc, CORE_MGMT_IP_PORT_CMDLINE_OPT);
+ bal_config_params.core_mgmt_ip_port = argv[++i];
+ }
+ else if (!strcmp(argv[i], BAL_API_IP_PORT_CMDLINE_OPT))
+ {
+ BAL_CHECK_IP_ARGUMENT(i, argc, BAL_API_IP_PORT_CMDLINE_OPT);
+ bal_config_params.balapi_mgmt_ip_port = argv[++i];
+ }
+#ifdef CONFIG_MAC_UTIL_IP_PORT
+ else if (!strcmp(argv[i], BAL_MAC_IP_PORT_CMDLINE_OPT))
+ {
+ /* When we build for x86, this is a necessary argument, because the MAC device is
+ * remote from the BAL core. When we build for WRX, this argument isn't required
+ * because the MAC device is local and the mac_rpc_ip_port value is not used.
+ */
+ BAL_CHECK_IP_ARGUMENT(i, argc, BAL_MAC_IP_PORT_CMDLINE_OPT);
+ bal_config_params.mac_rpc_ip_port = argv[++i];
+ }
+#endif
+#ifdef CONFIG_SWITCH_RPC
+ else if (!strcmp(argv[i], BAL_SW_IP_CMDLINE_OPT))
+ {
+ BAL_CHECK_IP_ARGUMENT(i, argc, BAL_SW_IP_CMDLINE_OPT);
+ bal_config_params.sw_rpc_ip = argv[++i];
+ }
+#endif
+ else if (!strcmp(argv[i], BAL_LEVEL_OPT))
+ {
+ ++i;
+ if (!strcmp(argv[i], "admin"))
+ bal_config_params.access = BCMCLI_ACCESS_ADMIN;
+ else if (!strcmp(argv[i], "guest"))
+ bal_config_params.access = BCMCLI_ACCESS_GUEST;
+ else if (!strcmp(argv[i], "debug"))
+ bal_config_params.access = BCMCLI_ACCESS_DEBUG;
+ else
+ return _usage(argv[0]);
+ }
+ else if (!strcmp(argv[i], BAL_NO_LINEEDIT_OPT))
+ {
+ bal_config_params.edit_mode = BCMCLI_LINE_EDIT_DISABLE;
+ }
+#ifdef ENABLE_LOG
+ else if (!strcmp(argv[i], BAL_NO_LOG_OPT))
+ {
+ bal_config_params.disable_log = BCMOS_TRUE;
+ }
+ else if (!strcmp(argv[i], BAL_LOG_SYSLOG_OPT))
+ {
+ bal_config_params.log_syslog = BCMOS_TRUE;
+ }
+ else if (!strcmp(argv[i], BAL_LOG_FILE_OPT))
+ {
+ if (i == argc - 1)
+ {
+ bcmos_printf("Log file name is expected after %s option\n", BAL_LOG_FILE_OPT);
+ return _usage(argv[0]);
+ }
+ bal_config_params.log_file_name = argv[++i];
+ }
+#endif
+ else if (!strcmp(argv[i], BAL_INIT_SCRIPT_OPT))
+ {
+ if (i == argc - 1)
+ {
+ bcmos_printf("Script file name is expected after %s option\n", BAL_INIT_SCRIPT_OPT);
+ return _usage(argv[0]);
+ }
+ bal_config_params.init_script = argv[++i];
+ }
+ else if (!strcmp(argv[i], BAL_HELP_OPT) || !strcmp(argv[i], BAL_LONG_HELP_OPT))
+ {
+ return _usage(argv[0]);
+ }
+ else
+ {
+ /* We have encountered a non-mandatory command line option
+ * that we don't recognize. This is a fatal error. Print
+ * the proper command line invocation.
+ */
+ printf("Error: unrecognized cmdline option specified (%s)\n", argv[i]);
+ return _usage(argv[0]);
+ }
+ }
+
+ /*
+ * The user MUST specify the mac and switch IP:port for IPC
+ */
+ if (BCMOS_FALSE
+#ifndef BAL_MONOLITHIC
+ || (NULL == bal_config_params.core_mgmt_ip_port) || (NULL == bal_config_params.balapi_mgmt_ip_port)
+#endif
+#ifdef CONFIG_MAC_UTIL_IP_PORT
+ || ((BCMOS_TRUE != bcmbal_is_mac_in_loopback()) && (NULL == bal_config_params.mac_rpc_ip_port))
+#endif
+#ifdef CONFIG_SWITCH_RPC
+ || (NULL == bal_config_params.sw_rpc_ip)
+#endif
+ )
+ {
+ printf("Error: you must enter ALL mandatory cmdline options\n");
+ return _usage(argv[0]);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* This is BAL initialization function that is called when BAL is compiled
+ * as a library rather than stand-alone application.
+ * \param[in] argc Number of command line parameters
+ * \param[in] argv Command line parameter array
+ * \returns BCM_ERR_OK (0) if successful or error<0 in case of failure
+ */
+bcmos_errno bcmbal_init(void)
+{
+ bcmos_errno ret;
+
+ /* Read the bal config file (bal_config.ini) parameters, if the config file is present */
+ bal_parse_config(&bal_config_params);
+
+ /* Now initialize the system topology */
+ ret = bcm_topo_init((bal_config_params.topo_params.num_of_devs &&
+ bal_config_params.topo_params.num_of_pons_per_dev &&
+ bal_config_params.topo_params.pon_mode != BCM_TOPO_PON_MODE_INVALID) ?
+ &bal_config_params.topo_params : NULL, TOPOLOGY_FILE_NAME);
+
+ if(BCM_ERR_OK != ret)
+ {
+ bcmos_printf("Error initializing the system topology\n");
+ return ret;
+ }
+
+#ifdef ENABLE_LOG
+ bal_core_log_init();
+#endif
+
+ /* Generate rpc.soc from rpc.soc.template */
+ if (BCM_ERR_OK != (ret = bal_rpc_soc_gen()))
+ return ret;
+
+ do
+ {
+
+ /* Initialize the BAL core itself
+ * NOTE: It is assumed that logging has been successfully
+ * initialized before this call is made
+ */
+ ret = bal_core_init();
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Error initializing the bal core\n");
+ break;
+ }
+
+ /* Initialize the switch utilities */
+ ret = sw_util_init();
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Error initializing the bal switch utilities\n");
+ break;
+ }
+
+ /* Initialize the mac utilities */
+ ret = mac_util_init(bal_config_params.mac_rpc_ip_port);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Error initializing the bal mac utilities\n");
+ break;
+ }
+
+ /* Initialize the bal public api */
+ ret = bcmbal_api_init(bal_config_params.balapi_mgmt_ip_port, bal_config_params.core_mgmt_ip_port);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Could not initialize the BAL Public API\n");
+ break;
+ }
+
+ bal_initialized = BCMOS_TRUE;
+
+ /* Print out the welcome banner */
+ welcome_to_bal();
+ }
+ while(0);
+
+ return ret;
+}
+
+void bcmbal_finish(void)
+{
+ bcmbal_cli_finish();
+ if (bal_initialized)
+ bal_core_finish();
+}
+
+/* Top-level init sequence */
+bcmos_errno bcmbal_init_all(int argc, char *argv[], bcmbal_exit_cb exit_cb)
+{
+ bcmos_errno err;
+ err = bcmbal_cmdline_parse(argc, argv);
+ err = (err != BCM_ERR_OK) ? err : bcmos_init();
+ err = (err != BCM_ERR_OK) ? err : bcmbal_log_init();
+ err = (err != BCM_ERR_OK) ? err : bcmbal_init();
+ err = (err != BCM_ERR_OK) ? err : bcmbal_cli_init(exit_cb);
+ return err;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core command line usage function
+ *
+ * A function to display the proper bal_core command line format
+ *
+ * @param cmd A pointer to the command line string that the user entered to
+ * start the BAL core.
+ *
+ * @returns BCM_ERR_PARM - This function is always run as a result of the user
+ * entering an invalid value on the command line.
+ *
+ *****************************************************************************/
+static bcmos_errno _usage(const char *cmd)
+{
+#ifndef BUILD_OF_AGENT
+ /* For SDN_AGENT all parm usage info is printed in the agent's main */
+ cl_print_usage(cmd, NULL, supported_cl_args, BCM_SIZEOFARRAY(supported_cl_args), CL_ARGUMENT_USAGE_FLAG_NONE);
+#endif
+ return BCM_ERR_PARM;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core initialization function
+ *
+ * A function to initialize the BAL core and all its associated threads.
+ *
+ * @returns BCM_ERR_OK, or the return value from first function called
+ * that fails.
+ *
+ *****************************************************************************/
+static bcmos_errno bal_core_init(void)
+{
+ bcmos_task_parm task_p = {};
+ bcmos_module_parm module_p = {};
+ bcmos_errno ret = BCM_ERR_OK;
+ mgmt_queue_addr_ports mgmt_queue_info;
+
+ do
+ {
+ /* Create message queues */
+ mgmt_queue_info.core_mgmt_ip_port = bal_config_params.core_mgmt_ip_port;
+ mgmt_queue_info.balapi_mgmt_ip_port = bal_config_params.balapi_mgmt_ip_port;
+ ret = core_msg_queue_init(&mgmt_queue_info);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create message queues\n");
+ break;
+ }
+
+ /* Create worker thread & modules for mgmt messages */
+ task_p.name = "core_worker";
+ task_p.priority = TASK_PRIORITY_WORKER;
+
+ ret = bcmos_task_create(&core_worker_thread, &task_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create worker thread\n");
+ break;
+ }
+
+ /*
+ * Initialize the worker thread that was just spawned
+ */
+ core_worker_thread_init();
+
+ /*
+ * Now create the module for the worker thread
+ */
+ module_p.qparm.name = "core_worker_mgmt_module";
+ module_p.init = _bal_worker_mgmt_module_init;
+ ret = bcmos_module_create(BCMOS_MODULE_ID_WORKER_MGMT, &core_worker_thread, &module_p);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create mgmt worker module\n");
+ break;
+ }
+
+#ifdef CONFIG_SWITCH_RPC
+ ret = sw_util_pkt_send_init(bal_config_params.sw_rpc_ip, bal_config_params.pkt_send_svr_listen_port);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't initialize the packet send interface ret = %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_core,
+ "\"Packet send\" interface is initialized"
+ " to use server at %s:%d\n",
+ bal_config_params.sw_rpc_ip, bal_config_params.pkt_send_svr_listen_port );
+ }
+#endif
+ }
+ while(0);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core finish function
+ *
+ * A function to clean up the BAL core and all its associated threads on
+ * exit.
+ *
+ * @returns BCM_ERR_OK
+ *
+ *****************************************************************************/
+static void bal_core_finish(void)
+{
+ rsc_mgr_uninit();
+ mac_util_finish();
+ sw_util_finish();
+
+ core_worker_thread_finish();
+
+ bcmos_module_destroy(BCMOS_MODULE_ID_WORKER_MGMT);
+
+ bcmos_task_destroy(&core_worker_thread);
+
+ /* Let logger task have enough time to drain its message queue. */
+#ifdef ENABLE_LOG
+ bcmos_usleep(1000000);
+ bcm_dev_log_destroy();
+#endif
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to print the welcome banner for BAL
+ *
+ * This function is executed at system startup time
+ *
+ *****************************************************************************/
+static void welcome_to_bal(void)
+{
+ time_t tm = time(NULL);
+
+ /* @todo Don't print the welcome banner when running as a daemon */
+
+ printf("%s", g_p_company_logo);
+
+ BCM_LOG(INFO, log_id_core, "*** Welcome to BAL %s version %s (Built: %s)\n",
+#ifndef BUILD_OF_AGENT
+ "",
+#else
+ "OF-Agent",
+#endif
+ BAL_VERSION, BAL_BUILD_DATE);
+ BCM_LOG(INFO, log_id_core, "%s\n", BAL_BUILD_INFO);
+
+ BCM_LOG(INFO, log_id_core, "Time is: %s", asctime(localtime(&tm)));
+
+#ifdef TEST_SW_UTIL_LOOPBACK
+ BCM_LOG(INFO, log_id_core, "----BUILT WITH TEST_SW_UTIL_LOOPBACK\n");
+#endif
+
+ if (BCMOS_TRUE == bcmbal_is_mac_in_loopback())
+ {
+ BCM_LOG(INFO, log_id_core, "----CONFIGURED WITH MAC UTIL LOOPBACK\n");
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief A trim helper function
+ *
+ * This function is used to get rid of trailing and leading whitespace
+ * including the "\n" from fgets()
+ *
+ * @param s A pointer to the string that is to be trimmed
+ *
+ * @returns -char *, the trimmed sting
+ *
+ */
+static char *trim (char * s)
+{
+ /* Initialize start, end pointers */
+ int len = strlen(s);
+ char *s1 = s, *s2 = &s[len - 1];
+
+ /* Trim and delimit right side */
+ while ( (isspace (*s2)) && (s2 >= s1) )
+ {
+ s2--;
+ len--;
+ }
+
+ *(s2+1) = '\0';
+
+ /* Trim left side */
+ while ( (isspace (*s1)) && (s1 < s2) )
+ {
+ s1++;
+ len--;
+ }
+
+ /* Copy finished string. Use memmove, as it is guaranteed to correctly handle overlapping strings. */
+ memmove (s, s1, len + 1);
+ return s;
+}
+
+/* A helper function for finding an enum array entry value, given it's name*/
+static long find_val_by_enum_name(bcmcli_enum_val *p_enum_array, const char * name)
+{
+ long val = -1;
+ int ii;
+
+
+ for(ii=0; p_enum_array[ii].name != NULL; ii++)
+ {
+ if(0 == strcmp(name, p_enum_array[ii].name))
+ {
+ val = p_enum_array[ii].val;
+ }
+ }
+
+ return val;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function that reads bal config file
+ *
+ * This function is used to read the bal config file into the
+ * bcmbal_config_params structure.
+ *
+ * The config file is defined to be named "bal_config.ini" and is
+ * of the format:
+ * param_name=param_value
+ *
+ * @param p_params A pointer to the core configuration parameters
+ *
+ * @returns void
+ *
+ */
+static void bal_parse_config(bcmbal_config_params *p_params)
+{
+ char *s, buff[MAX_CONFIG_FILE_LINE_LEN];
+ char name[MAX_CONFIG_PARAM_NAME_LEN], value[MAX_CONFIG_PARAM_VALUE_LEN];
+ FILE *fp = fopen (CONFIG_FILE_NAME, "r");
+
+ if (fp == NULL)
+ {
+ printf("No config file (%s) found\n", CONFIG_FILE_NAME);
+ return;
+ }
+
+ printf("BAL configuration params as read from %s:\n", CONFIG_FILE_NAME);
+
+ /* Read next line */
+ while ((s = fgets (buff, sizeof buff, fp)) != NULL)
+ {
+ /* Skip blank lines and comments */
+ if (buff[0] == '\n' || buff[0] == '#')
+ continue;
+
+ /* Parse name/value pair from line */
+ s = strtok (buff, "=");
+ if (s==NULL)
+ {
+ continue;
+ }
+ else
+ {
+ strncpy (name, s, MAX_CONFIG_PARAM_NAME_LEN);
+ }
+
+ s = strtok (NULL, "=");
+
+ if (s==NULL)
+ {
+ continue;
+ }
+ else
+ {
+ strncpy (value, s, MAX_CONFIG_PARAM_VALUE_LEN);
+ }
+
+ trim (value);
+
+ printf("%s=%s\n", name, value);
+
+ /* Copy into correct entry in parameters struct */
+ if(strcmp(name, "iwf_mode")==0)
+ {
+ p_params->iwf_mode = find_val_by_enum_name(iwf_mode_enum, value);
+ }
+ else if(strcmp(name, "intf_maptable")==0)
+ {
+ uint32_t intf_map_tbl_idx;
+
+ intf_map_tbl_idx = atoi(value);
+
+ if(BCM_ERR_OK != bal_bcm_intf_maptable_set(intf_map_tbl_idx))
+ {
+ printf("error: value (%u) is not a valid index, ignored", intf_map_tbl_idx);
+ }
+ else
+ {
+ p_params->intf_maptable = atoi(value);
+ }
+ }
+ else if(strcmp(name, "trap_udp_port")==0)
+ {
+ uint32_t udp_port;
+
+ udp_port = atoi(value);
+
+ if(BCM_ERR_OK != bal_bcm_trap_rcv_port_set(udp_port))
+ {
+ printf("error: value (%u) is not a valid port, ignored", udp_port);
+ }
+ else
+ {
+ p_params->trap_udp_port = udp_port;
+ }
+ }
+ else if(strcmp(name, "ds_sched_mode")==0)
+ {
+ uint32_t sched_mode;
+
+ sched_mode = atoi(value);
+
+ if(BCM_ERR_OK != bal_bcm_ds_sched_mode_set(sched_mode))
+ {
+ printf("error: value (%u) is not a valid sched mode, ignored", sched_mode);
+ }
+ else
+ {
+ p_params->ds_sched_mode = sched_mode;
+ }
+ }
+ else if(strcmp(name, "num_nni_ports")==0)
+ {
+
+ p_params->num_nni_ports = atoi(value);
+ bcm_topo_dev_set_max_nni(0, p_params->num_nni_ports);
+
+ }
+ else if(strcmp(name, "pkt_send_svr_listen_port")==0)
+ {
+
+ p_params->pkt_send_svr_listen_port = atoi(value);
+
+ }
+ else if(strcmp(name, "topology.num_of_devs")==0)
+ {
+ p_params->topo_params.num_of_devs = atoi(value);
+ }
+ else if(strcmp(name, "topology.num_of_pons_per_dev")==0)
+ {
+ p_params->topo_params.num_of_pons_per_dev = atoi(value);
+ }
+ else if(strcmp(name, "topology.pon_mode")==0)
+ {
+ if(strcmp(value, "gpon")==0)
+ p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_GPON;
+ else if(strcmp(value, "xgpon")==0)
+ p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_XGPON;
+ else if(strcmp(value, "xgs")==0)
+ p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_XGS;
+ else if(strcmp(value, "epon_tdma")==0)
+ p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_TDMA;
+ else if(strcmp(value, "epon_1g")==0)
+ p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_1G;
+ else if(strcmp(value, "epon_10g")==0)
+ p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_10G;
+ }
+ else if(strcmp(name, "mac_loopback")==0)
+ {
+ if(strcmp(value, "y")==0)
+ {
+ p_params->loopback_modes_bit_mask |= BIT_FIELD_MAC_IN_LOOPBACK;
+ }
+ }
+#ifdef OMCI_SVC
+ else if(strcmp(name, "omci_loopback")==0)
+ {
+ if(strcmp(value, "y")==0)
+ {
+ omci_svc_set_loopback(BCMOS_TRUE);
+ }
+ }
+#endif
+ else if(strncmp(name, "autoneg_nni", 11)==0)
+ {
+ int intf_id = atoi(name+11);
+ if ((unsigned)intf_id >= BAL_API_MAX_INTF_ID)
+ {
+ printf("error: %s: NNI %d is invalid, ignored", name, intf_id);
+ continue;
+ }
+ if(strcmp(value, "y")==0)
+ {
+ p_params->nni_autoneg_bit_mask |= (1 << intf_id);
+ }
+ }
+
+ else
+ {
+ printf("%s/%s: Unknown name/value config file pair!\n",name, value);
+ }
+ }//while
+
+ printf("\n");
+
+ /* Close file */
+ fclose (fp);
+}
+
+static bcmos_errno bal_rpc_soc_gen(void)
+{
+#ifndef TEST_SW_UTIL_LOOPBACK
+#ifdef CONFIG_SWITCH_RPC
+ char cmd[MAX_CMD_LINE_LEN];
+ FILE *fp = fopen (RPC_SOC_TEMPLATE_FILE_NAME, "r");
+ int rc;
+
+ if (fp == NULL)
+ {
+ printf("%s not found\n", RPC_SOC_TEMPLATE_FILE_NAME);
+ return BCM_ERR_NOENT;
+ }
+ fclose (fp);
+
+ snprintf(cmd, MAX_CMD_LINE_LEN, "sed -e \"s/\\\\\\$DIP\\\\$/%s/\" %s > %s",
+ bal_config_params.sw_rpc_ip, RPC_SOC_TEMPLATE_FILE_NAME, RPC_SOC_FILE_NAME);
+ rc = system(cmd);
+ if (rc || WEXITSTATUS(rc))
+ {
+ printf("Failed to generate %s from %s\n", RPC_SOC_FILE_NAME, RPC_SOC_TEMPLATE_FILE_NAME);
+ return BCM_ERR_INTERNAL;
+ }
+#endif
+#endif
+ return BCM_ERR_OK;
+}
+
+
+uint16_t bcmbal_num_nni_ports_get(void)
+{
+ return bal_config_params.num_nni_ports;
+}
+
+bcmos_bool bcmbal_is_mac_in_loopback(void)
+{
+ return IS_MAC_IN_LOOPBACK(bal_config_params.loopback_modes_bit_mask);
+}
+
+bcmos_bool bcmbal_is_nni_autoneg_on(bcmbal_intf_id intf_id)
+{
+ return IS_NNI_INTF_AUTONEG_ON(bal_config_params.nni_autoneg_bit_mask, intf_id);
+}
+
+/* Get supported command line argument list */
+int bcmbal_supported_args_get(cl_argument supported_args[], int size)
+{
+ int i;
+ for (i=0; i<BCM_SIZEOFARRAY(supported_cl_args); i++)
+ {
+ if (i < size)
+ supported_args[i] = supported_cl_args[i];
+ }
+ return i;
+}
+
+/* Get BAL configuration */
+const bcmbal_config_params *bcmbal_config_get(void)
+{
+ return &bal_config_params;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/main/bal_core.h b/bal_release/src/core/main/bal_core.h
new file mode 100644
index 0000000..4410c47
--- /dev/null
+++ b/bal_release/src/core/main/bal_core.h
@@ -0,0 +1,117 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_core.h
+ * @brief The include files common to all core files
+ *
+ * @addtogroup ctrlr
+ */
+
+
+#ifndef COREMAIN_H
+#define COREMAIN_H
+
+/*@{*/
+#include <bcmos_system.h>
+#include <bal_objs.h>
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+#endif
+#include <bcm_topo.h>
+#include <cmdline.h>
+
+extern dev_log_id log_id_core;
+
+
+#define BIT_FIELD_MAC_IN_LOOPBACK 0x01
+#define BIT_FIELD_SWITCH_IN_LOOPBACK 0x02
+#define IS_MAC_IN_LOOPBACK(config) ((config) & BIT_FIELD_MAC_IN_LOOPBACK)
+#define IS_NNI_INTF_AUTONEG_ON(config, intf) (config & (1 << intf))
+
+typedef struct bcmbal_config_params
+{
+ bcmbal_iwf_mode iwf_mode;
+ uint32_t intf_maptable;
+ uint32_t trap_udp_port;
+ uint16_t num_nni_ports;
+ uint32_t ds_sched_mode;
+ uint32_t pkt_send_svr_listen_port; /* The port number where the bcm.user process listens for packet send messages from the core */
+ uint8_t loopback_modes_bit_mask; /* mac | switch | something else in loopback mode */
+ bcm_topo_params topo_params;
+ uint32_t nni_autoneg_bit_mask; /* NNI autoneg is ON */
+
+ /*
+ * IP:Port strings specifying IP:Port assignments of the queues
+ * required for IPC between BAL components
+ */
+ const char *core_mgmt_ip_port;
+ const char *balapi_mgmt_ip_port;
+ const char *mac_rpc_ip_port;
+ const char *sw_rpc_ip;
+
+ /* CLI session configuration */
+ bcmcli_access_right access;
+ bcmcli_line_edit_mode edit_mode;
+ const char *init_script;
+
+ /* Logger parameters */
+ bcmos_bool disable_log;
+ const char *log_file_name;
+ bcmos_bool log_syslog;
+} bcmbal_config_params;
+
+extern bcmos_errno bcmbal_init(void);
+extern void bcmbal_finish(void);
+extern int bcmbal_supported_args_get(cl_argument supported_args[], int size);
+extern bcmos_errno bcmbal_cmdline_parse(int argc, char *argv[]);
+extern bcmos_errno bcmbal_log_init(void);
+extern const bcmbal_config_params *bcmbal_config_get(void);
+
+typedef void (* bcmbal_exit_cb)(void);
+
+/* Top-level initialization sequence
+ * - parse commend line
+ * - initialize OS abstraction
+ * - initialize logger
+ * - initialize BAL core and utils
+ * - initialize BAL CLI
+ */
+extern bcmos_errno bcmbal_init_all(int argc, char *argv[], bcmbal_exit_cb exit_cb);
+
+extern bcmos_bool bcmbal_is_mac_in_loopback(void);
+
+extern bcmos_bool bcmbal_is_nni_autoneg_on(bcmbal_intf_id intf_id);
+
+/*@}*/
+
+#endif /*COREMAIN_H*/
+
diff --git a/bal_release/src/core/main/bal_worker.c b/bal_release/src/core/main/bal_worker.c
new file mode 100644
index 0000000..98f50be
--- /dev/null
+++ b/bal_release/src/core/main/bal_worker.c
@@ -0,0 +1,793 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_worker.c
+ * @brief Initialization and message handler functions for the BAL Core
+ * worker thread including all core FSM initialization.
+ *
+ * @addtogroup ctrlr
+ */
+
+/*@{*/
+
+/* Project includes */
+#include <bcmos_system.h>
+#include <bal_api.h>
+#include <bal_msg.h>
+#include <bal_osmsg.h>
+#include "bal_worker.h"
+#include "acc_term_fsm.h"
+#include "flow_fsm.h"
+#include "group_fsm.h"
+#include "sub_term_fsm.h"
+#include "tm_sched_fsm.h"
+#include "tm_queue_fsm.h"
+#include "fsm_common.h"
+#include "bal_api_worker.h"
+#include "bal_obj_msg_pack_unpack.h"
+
+#include "bal_dpp_acc_term.h"
+#include "rsc_mgr.h"
+
+#include <arpa/inet.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+/*
+ * @brief The logging device id for the core
+ */
+extern dev_log_id log_id_core;
+#endif
+
+/* Local function declarations */
+static void core_mgmt_msg_handler(bcmos_module_id module_id, bcmos_msg *msg);
+static bcmos_errno process_mgmt_msg(void *msg_payload);
+static bcmos_errno process_util_msg(void *msg_payload);
+
+static int _bal_mgmt_rx_handler(long data);
+
+static bcmos_errno process_packet_object(void *msg_payload);
+
+/*
+ * @brief The BAL core management queue. These are the queues through which the core
+ * converses with the Public API. The remote endpoint of these queues are the
+ * BAL API backend.
+ */
+static bcmos_msg_queue core_mgmt_queue;
+static bcmos_msg_queue core_api_queue;
+static bcmos_msg_queue core_api_ind_queue;
+bcmos_msg_queue *p_bal_core_queue;
+bcmos_msg_queue *p_bal_core_to_api_queue;
+bcmos_msg_queue *p_bal_core_to_api_ind_queue;
+
+/*
+ * @brief The rx thread for management message reception
+ */
+static bcmos_task rx_mgmt_thread;
+
+/*****************************************************************************/
+/**
+ * @brief Initialize the worker thread
+ *
+ * A Worker module function that initializes all of the data structures and
+ * FSMs associated with the BAL core. This function called from bal_core_init
+ * during BAL core startup.
+ *
+ *****************************************************************************/
+void core_worker_thread_init(void)
+{
+ /*
+ * Initialize all of the worker thread hosted FSMs and the resource manager
+ */
+
+ rsc_mgr_init();
+
+ tm_queue_fsm_init();
+
+ tm_sched_fsm_init();
+
+ access_terminal_fsm_init();
+
+ flow_fsm_init();
+
+ sub_term_fsm_init();
+
+ group_fsm_init();
+
+
+ return;
+}
+
+/*****************************************************************************/
+/**
+ * @brief Finish the worker thread
+ *
+ * A Worker module function that un-initializes all of the data structures and
+ * FSMs associated with the BAL core. This function called from bal_core_init
+ * during BAL core cleanup on exit.
+ *
+ *****************************************************************************/
+void core_worker_thread_finish(void)
+{
+ /*
+ * Un-initialize the worker thread owned data structures. etc.
+ */
+ bcmos_msg_unregister(BCMBAL_MGMT_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT);
+
+ bcmos_msg_unregister(BCMBAL_MAC_UTIL_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT);
+
+ bcmos_task_destroy(&rx_mgmt_thread);
+
+ sub_term_fsm_finish();
+
+ flow_fsm_finish();
+
+ group_fsm_finish();
+
+ tm_sched_fsm_finish();
+
+ tm_queue_fsm_finish();
+
+ bcmos_msg_queue_destroy(&core_mgmt_queue);
+
+ if (p_bal_core_to_api_queue == &core_api_queue)
+ bcmos_msg_queue_destroy(p_bal_core_to_api_queue);
+
+ if (p_bal_core_to_api_ind_queue == &core_api_ind_queue)
+ bcmos_msg_queue_destroy(p_bal_core_to_api_ind_queue);
+
+ return;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core management message queue init
+ *
+ * A initialization function for the worker module.
+ * It creates message queues for communication with API layer and UTILS
+ *
+ * @param mgmt_queue_info A pointer to the ip:port addresses required for the msg queues.
+ * The ip:port addresses can be NULL in BAL_MONOLITHIC mode. In this case
+ * inter-thread queues will be used for communication.
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+bcmos_errno core_msg_queue_init(mgmt_queue_addr_ports *mgmt_queue_info)
+{
+ bcmos_msg_queue_parm msg_q_p = {};
+ bcmos_errno ret;
+
+ do
+ {
+ /* Create core queue. BAL core listens on this queue
+ * for public API calls and indications from the UTils
+ */
+ msg_q_p.name = "mgmt_rx_q";
+ if (NULL != mgmt_queue_info->core_mgmt_ip_port)
+ {
+ /* The queue allows sending from core_mgmt_ip_port and receiving at core_mgmt_ip_port */
+ msg_q_p.local_ep_address = mgmt_queue_info->core_mgmt_ip_port;
+ msg_q_p.remote_ep_address = mgmt_queue_info->core_mgmt_ip_port;
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
+ }
+ else
+ {
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_LOCAL;
+ }
+ ret = bcmos_msg_queue_create(&core_mgmt_queue, &msg_q_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create rx mgmt queue\n");
+ break;
+ }
+ p_bal_core_queue = &core_mgmt_queue;
+#ifdef BAL_MONOLITHIC
+ if (NULL == mgmt_queue_info->core_mgmt_ip_port)
+ p_balapi_to_core_queue = p_bal_core_queue;
+#endif
+
+ /* Now create a TX queue for sending replies from the core to API.
+ * Only do it if using socket transport. In case of inter-thread queues
+ * it will be created by API layer
+ */
+ if (NULL != mgmt_queue_info->balapi_mgmt_ip_port)
+ {
+ uint16_t portnum;
+ char *p_portnum_str;
+ char balapi_ind_port_str[256];
+
+ msg_q_p.name = "mgmt_to_api_q";
+ msg_q_p.local_ep_address = NULL;
+ msg_q_p.remote_ep_address = mgmt_queue_info->balapi_mgmt_ip_port;
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
+ ret = bcmos_msg_queue_create(&core_api_queue, &msg_q_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create tx mgmt queue\n");
+ break;
+ }
+ p_bal_core_to_api_queue = &core_api_queue;
+
+ /*
+ * make a copy of the user chosen bal api mgmt port
+ */
+ strcpy(balapi_ind_port_str, mgmt_queue_info->balapi_mgmt_ip_port);
+
+ /* Find the port number */
+ p_portnum_str = strchr(balapi_ind_port_str, ':') + 1;
+
+ /* convert to an integer and increment it by one */
+ portnum = atoi(p_portnum_str) + 1;
+
+ /* create the new string defining the BAL API indication port */
+ sprintf(p_portnum_str,"%d", portnum);
+
+ /* Create core->API indication queue
+ */
+ msg_q_p.name = "mgmt_ind_q";
+
+ /* Set up the management IP:port access parameters to allow the core to send indications to
+ * the BAL public API - this is a TX queue only!.
+ */
+ msg_q_p.local_ep_address = NULL;
+ msg_q_p.remote_ep_address = balapi_ind_port_str;
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
+
+ ret = bcmos_msg_queue_create(&core_api_ind_queue, &msg_q_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create the core tx indication queue\n");
+ break;
+ }
+
+ BCM_LOG(DEBUG, log_id_core, "Created the core tx indication queue\n");
+
+ p_bal_core_to_api_ind_queue = &core_api_ind_queue;
+ }
+ } while (0);
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core management worker module init
+ *
+ * A initialization function for the worker module.
+ * It registers for messages that this module is expected to process.
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+bcmos_errno _bal_worker_mgmt_module_init(long data)
+{
+
+ bcmos_task_parm task_p = {};
+ bcmos_errno ret = BCM_ERR_OK;
+
+ do
+ {
+
+ /* Create Mgmt RX thread */
+ task_p.name = "mgmt_mgmt_rx";
+ task_p.priority = TASK_PRIORITY_IPC_RX;
+ task_p.handler = _bal_mgmt_rx_handler;
+ task_p.data = (long)p_bal_core_queue;
+
+ ret = bcmos_task_create(&rx_mgmt_thread, &task_p);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_core, "Couldn't create Mgmt RX thread\n");
+ break;
+ }
+
+ /* Register the message types to be handled by the mgmt module
+ */
+ bcmos_msg_register(BCMBAL_MGMT_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT, core_mgmt_msg_handler);
+ bcmos_msg_register(BCMBAL_MAC_UTIL_MSG, 0, BCMOS_MODULE_ID_WORKER_MGMT, core_util_msg_handler);
+ }
+ while(0);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief Mgmt RX handler
+ *
+ * This handler is executed in the context of an RX thread. It's purpose
+ * is to dispatch the message received here to the module that has registered
+ * to process this message. The message is then processed in the context
+ * of the thread to which that module is attached.
+ *
+ * @param data A pointer to the received message
+ *
+ * @returns 0 on success, -EINVAL on failure
+ *
+ *****************************************************************************/
+static int _bal_mgmt_rx_handler(long data)
+{
+ bcmos_msg_queue *rxq = (bcmos_msg_queue *)data;
+ bcmos_task *my_task = bcmos_task_current();
+ void *payload;
+ bcmos_msg *msg;
+ bcmos_errno ret = BCM_ERR_OK;
+
+ while (!my_task->destroy_request)
+ {
+ payload = NULL;
+ ret = bcmbal_msg_recv(rxq, BCMOS_WAIT_FOREVER, &payload);
+ if (ret)
+ {
+ /* Unexpected failure */
+ BCM_LOG(ERROR, log_id_core, "bcmbal_msg_recv() -> %s\n", bcmos_strerror(ret));
+ continue;
+ }
+
+ /* Message received */
+ BCM_LOG(DEBUG, log_id_core, "bcmbal_msg_recv(%p) -> %s\n", payload, bcmos_strerror(ret));
+
+ /*
+ * Got a message, so now dispatch it. This will result in one
+ * of the modules (registered for the message being processed)
+ * executing its message callback handler.
+ *
+ */
+ msg = bcmbal_bcmos_hdr_get(payload);
+ ret = bcmos_msg_dispatch(msg, BCMOS_MSG_SEND_AUTO_FREE);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_core,
+ "Couldn't dispatch message %d:%d\n",
+ (int)msg->type, (int)msg->instance);
+ }
+ }
+
+ my_task->destroyed = BCMOS_TRUE;
+
+ return (BCM_ERR_OK == ret) ? 0 : -EINVAL;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core management message handler
+ *
+ * A function that handlers messages received from the
+ * BAL public API via an RX thread.
+ *
+ * This function executes in the context of the worker thread.
+ *
+ * @param module_id The index of the module that this message handler
+ * is associated with.
+ *
+ * @param msg A pointer to the received message to be processed
+ *
+ *****************************************************************************/
+static void core_mgmt_msg_handler(bcmos_module_id module_id, bcmos_msg *msg)
+{
+
+ void *msg_payload;
+
+ /* Parameter checks */
+ BUG_ON(NULL == msg);
+
+ /*
+ * @to-do
+ * validate the message major and minor version is correct
+ */
+
+ /*
+ * Point to the message payload for further processing
+ */
+ msg_payload = bcmbal_payload_ptr_get(bcmbal_bal_hdr_get_by_bcmos_hdr(msg));
+
+ /*
+ * These are messages from the BAL Public API or the UTILS
+ *
+ * - call into appropriate FSM
+ *
+ */
+ BCM_LOG(DEBUG, log_id_core, "Received a mgmt message (payload at %p)\n", msg_payload);
+
+
+ if(BCMBAL_MGMT_MSG == bcmbal_type_major_get(msg_payload) &&
+ BAL_SUBSYSTEM_PUBLIC_API == bcmbal_sender_get(msg_payload))
+ {
+ /* Process the message */
+ process_mgmt_msg(msg_payload);
+ }
+ else
+ {
+ BCM_LOG(FATAL, log_id_core, "message received with wrong major type/subsystem combination (%d/\%d)\n",
+ bcmbal_type_major_get(msg_payload),
+ bcmbal_sender_get(msg_payload));
+
+ BUG_ON(BCMOS_TRUE);
+ }
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core management message processing function
+ *
+ * A Worker module function that handles messages received from the
+ * BAL public API or UTILs via an RX thread.
+ *
+ * This function executes in the context of the worker thread
+ *
+ * @param msg_payload A pointer to the message to be processed
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+static bcmos_errno process_mgmt_msg(void *msg_payload)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_obj_id objtype;
+
+ BCM_LOG(DEBUG, log_id_core, "Processing a management message\n");
+
+ objtype = bcmbal_msg_id_obj_get(msg_payload);
+
+ /*
+ * Process the message based on the type of BAL object and sender
+ * in the message.
+ */
+ switch(objtype)
+ {
+ case BCMBAL_OBJ_ID_FLOW:
+ {
+ ret = process_flow_object(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_GROUP:
+ {
+ ret = process_group_object(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
+ {
+ ret = process_access_terminal_object(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_INTERFACE:
+ {
+ ret = process_interface_object(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
+ {
+ ret = process_subscriber_terminal_object(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_PACKET:
+ {
+
+ ret = process_packet_object(msg_payload);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, ((bcmbal_obj *)msg_payload)->type, log_id_core);
+
+ break;
+
+ }
+
+ case BCMBAL_OBJ_ID_TM_SCHED:
+ {
+ ret = process_tm_sched_object(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_TM_QUEUE:
+ {
+ ret = process_tm_queue_object(msg_payload);
+ break;
+ }
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_core,
+ "Unsupported object detected in management message\n");
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, ((bcmbal_obj *)msg_payload)->type, log_id_core);
+
+ break;
+ }
+ }
+ bcmbal_msg_free(msg_payload);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core util message handler
+ *
+ * A function that handlers messages received from the
+ * BAL utils via an RX thread.
+ *
+ * This function executes in the context of the worker thread.
+ *
+ * @param module_id The index of the module that this message handler
+ * is associated with.
+ *
+ * @param msg A pointer to the received message to be processed
+ *
+ *****************************************************************************/
+void core_util_msg_handler(bcmos_module_id module_id, bcmos_msg *msg)
+{
+
+ void *msg_payload;
+
+ /* Parameter checks */
+ BUG_ON(NULL == msg);
+
+ /*
+ * @to-do
+ * validate the message major and minor version is correct
+ */
+
+ /*
+ * Point to the message payload for further processing
+ */
+ msg_payload = bcmbal_payload_ptr_get(bcmbal_bal_hdr_get_by_bcmos_hdr(msg));
+
+ /*
+ * These are messages from the BAL Utils
+ *
+ * - call into appropriate FSM
+ *
+ */
+ BCM_LOG(DEBUG, log_id_core, "Received a Util message (payload at %p)\n", msg_payload);
+
+ if(BCMBAL_MAC_UTIL_MSG == bcmbal_type_major_get(msg_payload) &&
+ BAL_SUBSYSTEM_MAC_UTIL == bcmbal_sender_get(msg_payload))
+ {
+ /* Process the message */
+ process_util_msg(msg_payload);
+
+ }
+ else
+ {
+ BCM_LOG(FATAL, log_id_core, "message received with wrong major type/subsystem combination (%d/\%d)\n",
+ bcmbal_type_major_get(msg_payload),
+ bcmbal_sender_get(msg_payload));
+
+ BUG_ON(BCMOS_TRUE);
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core util message processing function
+ *
+ * A Worker module function that handles messages received from the
+ * BAL utils via an RX thread.
+ *
+ * This function executes in the context of the worker thread
+ *
+ * @param msg_payload A pointer to the message to be processed
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+static bcmos_errno process_util_msg(void *msg_payload)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_obj_id objtype;
+
+ BCM_LOG(DEBUG, log_id_core, "Processing a util message\n");
+
+ objtype = bcmbal_msg_id_obj_get(msg_payload);
+
+ /*
+ * Process the util message based on the type of BAL object
+ * in the message.
+ */
+ switch(objtype)
+ {
+ case BCMBAL_OBJ_ID_FLOW:
+ {
+ ret = process_flow_util_msg(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_GROUP:
+ {
+ ret = process_group_util_msg(msg_payload);
+ break;
+ }
+
+
+ case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
+ {
+ ret = process_access_terminal_util_msg(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_INTERFACE:
+ {
+ ret = process_interface_util_msg(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
+ {
+ ret = process_subscriber_terminal_util_msg(msg_payload);
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_TM_SCHED:
+ {
+ ret = process_tm_sched_util_msg(msg_payload);
+ break;
+ }
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_core,
+ "Unsupported object detected in message received from util\n");
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ break;
+ }
+ }
+ /*
+ * Free the message after processing
+ */
+ bcmbal_msg_free(msg_payload);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The BAL core "packet send" message processing function
+ *
+ * A Worker module function that handles packet send messages received from the
+ * BAL public API via an RX thread.
+ *
+ * This function executes in the context of the worker thread
+ *
+ * @param msg_payload A pointer to the message to be processed
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+static bcmos_errno process_packet_object(void *msg_payload)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ uint8_t *p_user_pkt;
+ uint16_t user_pkt_len;
+ uint8_t dst_port_id;
+ bcmos_bool b_port_id_is_nni;
+ bcmbal_packet_cfg *p_packet_obj;
+ uint16_t tunnel_tag_vlan_id = 0;
+
+ BCM_LOG(DEBUG, log_id_core, "Processing a \"Packet send\" message\n");
+
+ p_packet_obj = (bcmbal_packet_cfg *)msg_payload;
+
+ /* Extract the length of the user packet to be proxied */
+ user_pkt_len = p_packet_obj->data.pkt.len;
+
+ /* Derive a pointer to the user packet */
+ p_user_pkt = p_packet_obj->data.pkt.val;
+
+ BCM_LOG(DEBUG, log_id_core, "user packet first 12 bytes %02X%02X%02X%02X%02X%02X %02X%02X%02X%02X%02X%02X\n",
+ p_user_pkt[0], p_user_pkt[1], p_user_pkt[2], p_user_pkt[3], p_user_pkt[4], p_user_pkt[5],
+ p_user_pkt[6], p_user_pkt[7], p_user_pkt[8], p_user_pkt[9], p_user_pkt[10], p_user_pkt[11]);
+
+ /* Is this packet destined to an NNI or PON port? */
+ b_port_id_is_nni = (BCMBAL_DEST_TYPE_NNI == p_packet_obj->key.packet_send_dest.type) ?
+ BCMOS_TRUE : BCMOS_FALSE;
+
+ /*
+ * Process the message based on the type of BAL object
+ * in the message.
+ */
+ switch(p_packet_obj->hdr.hdr.obj_type)
+ {
+ case BCMBAL_OBJ_ID_PACKET:
+ {
+
+ dst_port_id = (BCMOS_TRUE == b_port_id_is_nni) ?
+ (p_packet_obj->key.packet_send_dest.u.nni.int_id) :
+ (p_packet_obj->key.packet_send_dest.u.sub_term.int_id);
+ if(BCMOS_FALSE == b_port_id_is_nni)
+ {
+ /*
+ * Packets destined to a PON interface require a tunnel tag
+ *
+ * Get the svc_port_id for the first flow on the subscriber terminal (if there is one)
+ */
+ if(BCM_ERR_OK != svc_port_id_for_sub_term_ds_flow_get(p_packet_obj->key.packet_send_dest.u.sub_term.int_id,
+ p_packet_obj->key.packet_send_dest.u.sub_term.sub_term_id,
+ p_packet_obj->key.packet_send_dest.u.sub_term.sub_term_uni,
+ &tunnel_tag_vlan_id))
+ {
+ BCM_LOG(ERROR,
+ log_id_core,
+ "Packet send could not find any downstream FLOW to send packet for sub_term_id %d (PON %d)\n",
+ p_packet_obj->key.packet_send_dest.u.sub_term.sub_term_id,
+ p_packet_obj->key.packet_send_dest.u.sub_term.int_id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ }
+
+ ret = sw_util_pkt_send(dst_port_id,
+ (b_port_id_is_nni ? REASON_SEND_TO_NNI : REASON_SEND_TO_PON),
+ p_user_pkt,
+ user_pkt_len,
+ (int)tunnel_tag_vlan_id);
+ }
+ break;
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_core,
+ "Unsupported object detected in \"packet send\" message\n");
+ ret = BCM_ERR_NOT_SUPPORTED;
+ }
+ break;
+
+ }
+ /*
+ * NOTE: DO NOT free the message after processing here. It is freed in the calling function
+ */
+
+ return ret;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/main/bal_worker.h b/bal_release/src/core/main/bal_worker.h
new file mode 100644
index 0000000..a0df6ae
--- /dev/null
+++ b/bal_release/src/core/main/bal_worker.h
@@ -0,0 +1,72 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_worker.h
+ *
+ * @brief Bal worker thread include file
+ *
+ * Module contains the data structures and functions used to support the
+ * BAL core worker thread.
+ *
+ * @defgroup ctrlr Core Controller
+ * @ingroup core
+ *
+ */
+
+#ifndef BALWORKER_H
+#define BALWORKER_H
+
+/*@{*/
+
+#include <bcmos_errno.h>
+#include <bal_api.h>
+
+/* Transmit Queues to and from BAL core */
+extern bcmos_msg_queue *p_bal_core_to_api_queue;
+extern bcmos_msg_queue *p_bal_core_to_api_ind_queue;
+
+/*
+ * Function declarations
+ */
+extern bcmos_errno _bal_worker_mgmt_module_init(long data);
+extern bcmos_errno _bal_worker_util_module_init(long data);
+
+extern bcmos_errno core_msg_queue_init(mgmt_queue_addr_ports *msg_queue_info);
+extern void core_worker_thread_init(void);
+extern void core_worker_thread_finish(void);
+
+extern void core_util_msg_handler(bcmos_module_id module_id, bcmos_msg *msg);
+
+
+/*@}*/
+
+#endif /* BALWORKER_H */
diff --git a/bal_release/src/core/main/flow_fsm.c b/bal_release/src/core/main/flow_fsm.c
new file mode 100644
index 0000000..f7ee71a
--- /dev/null
+++ b/bal_release/src/core/main/flow_fsm.c
@@ -0,0 +1,2556 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file flow_fsm.c
+ * @brief Code to support the BAL flow FSM
+ *
+ * @addtogroup flow
+ *
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <flow_fsm.h>
+#include <tm_sched_fsm.h>
+#include <tm_queue_fsm.h>
+
+
+#include <bal_msg.h>
+#include <bal_osmsg.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include "rsc_mgr.h"
+
+#include <bal_objs.h>
+#include <fsm_common.h>
+#include <bal_switch_flow.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+ /*
+ * @brief The logging device id for flow
+ */
+static dev_log_id log_id_flow;
+#endif
+
+/* local function declarations */
+static bcmos_errno flow_fsm_admin_up_start(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_admin_up_error(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_admin_dn_start(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_admin_dn_ok(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_admin_dn_error(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_ignore_util_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_removing_process_util_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_removing_process_util_auto_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_null_process_util_auto_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_process_util_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_process_util_auto_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_clear_start(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+
+static bcmos_errno flow_fsm_state_err(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event);
+
+static bcmos_errno flow_fsm_exec(flow_inst *p_flow_inst, flow_fsm_event *p_event);
+
+static flow_inst *flow_inst_get(bcmbal_flow_key *key, flow_flag search_flag, bcmos_bool *is_new_flow);
+
+
+#ifdef FREE_FLOW_BY_KEY_SUPPORTED
+static bcmos_errno flow_free_by_key(bcmbal_flow_key *key);
+#endif
+static bcmos_errno flow_free_by_entry(flow_inst *p_entry);
+
+static bcmos_errno flow_tm_get(bcmbal_flow_cfg *p_flow_info, tm_sched_inst **p_tm_sched_inst);
+static bcmos_errno flow_queue_validate(bcmbal_flow_cfg *p_flow_cfg, tm_queue_inst **p_tm_queue_inst);
+
+
+/*
+ * @brief The Global flow fsm context data structure
+ */
+static flow_fsm_ctx g_flow_fsm_flow_list_ctx;
+
+/*
+ * Macros for flow ctx access
+ */
+#define FLOW_FSM_FLOW_LIST_CTX (g_flow_fsm_flow_list_ctx)
+#define FLOW_FSM_FLOW_LIST_CTX_PTR (&g_flow_fsm_flow_list_ctx)
+
+/*
+ * @brief The definition of a flow FSM state processing function
+ */
+typedef bcmos_errno (* flow_fsm_state_processor)(flow_inst *, void *, flow_fsm_event *);
+
+/*
+ * @brief The Flow FSM state processing array
+ */
+static flow_fsm_state_processor flow_states[FLOW_FSM_STATE__NUM_OF][FLOW_FSM_EVENT_TYPE__NUM_OF] =
+{
+
+ [FLOW_FSM_STATE_NULL] =
+ {
+ /*
+ * Next state: CONFIGURING
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_start,
+
+ /*
+ * Next state: NULL
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_ok,
+
+ /*
+ * Next state: NULL
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_ignore_util_msg,
+
+ /*
+ * Next state: NULL
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_null_process_util_auto_msg,
+ },
+ [FLOW_FSM_STATE_CONFIGURING] =
+ {
+ /*
+ * Next state: CONFIGURING
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_start,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_start,
+
+ /*
+ * Next state: CONFIGURING | CONFIGURED
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_process_util_msg,
+
+ /*
+ * Next state: REMOVING
+ */
+ [FLOW_FSM_EVENT_TYPE_REMOVE] = flow_fsm_clear_start,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_process_util_auto_msg,
+
+ },
+
+ [FLOW_FSM_STATE_CONFIGURED] =
+ {
+ /*
+ * Next state: CONFIGURED
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_start,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_start,
+
+ /*
+ * Next state: REMOVING
+ */
+ [FLOW_FSM_EVENT_TYPE_REMOVE] = flow_fsm_clear_start,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_process_util_msg,
+
+ /*
+ * Next state: CONFIGURED
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_process_util_auto_msg,
+
+ },
+
+ [FLOW_FSM_STATE_REMOVING] =
+ {
+ /*
+ * Next state: REMOVING
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_UP] = flow_fsm_admin_up_error,
+
+ /*
+ * Next state: REMOVING
+ */
+ [FLOW_FSM_EVENT_TYPE_ADMIN_DN] = flow_fsm_admin_dn_error,
+
+ /*
+ * Next state: REMOVING | NULL
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_MSG] = flow_fsm_removing_process_util_msg,
+
+ /*
+ * Next state: REMOVING
+ */
+ [FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = flow_fsm_removing_process_util_auto_msg,
+ },
+
+};
+
+static char *state_name_str[] =
+{
+ "FLOW_FSM_STATE_NULL",
+ "FLOW_FSM_STATE_CONFIGURING",
+ "FLOW_FSM_STATE_CONFIGURED",
+ "FLOW_FSM_STATE_REMOVING",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (FLOW_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), flow_fsm_state);
+
+static char *flow_state_name_get(flow_fsm_state state)
+{
+ if(state < FLOW_FSM_STATE__LAST)
+ {
+ return state_name_str[state];
+ }
+ else
+ {
+ return "FLOW_UNKNOWN";
+ }
+}
+
+static char *event_name_str[] =
+{
+ "FLOW_FSM_ADMIN_UP_EVENT",
+ "FLOW_FSM_ADMIN_DN_EVENT",
+ "FLOW_FSM_REMOVE_EVENT",
+ "FLOW_FSM_UTIL_MSG_EVENT",
+ "FLOW_FSM_UTIL_AUTO_MSG_EVENT",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (FLOW_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), flow_fsm_event_type);
+
+static char *flow_event_name_get(flow_fsm_event_type event)
+{
+ if(event < FLOW_FSM_EVENT_TYPE__LAST)
+ {
+ return event_name_str[event];
+ }
+ else
+ {
+ return "FLOW_EVT_UNKNOWN";
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the current_flow_info object of the
+ * supplied entry.
+ *
+ * @param p_entry A pointer to the entry to be initialized
+ *
+ *
+ * @returns void
+ *****************************************************************************/
+static void flow_inst_entry_obj_init(flow_inst *p_entry)
+{
+ /* The actual key content is irrelevant for free flows */
+ bcmbal_flow_key key = { .flow_id = 0, .flow_type = BCMBAL_FLOW_TYPE_DOWNSTREAM };
+
+ BCMBAL_CFG_INIT(&p_entry->current_flow_info,
+ flow,
+ key);
+
+ BCMBAL_CFG_PROP_SET(&p_entry->current_flow_info,
+ flow,
+ admin_state,
+ BCMBAL_STATE_DOWN);
+
+ BCMBAL_CFG_PROP_SET(&p_entry->current_flow_info,
+ flow,
+ oper_status,
+ BCMBAL_STATUS_DOWN);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_flow_info), BCMOS_FALSE);
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the Flow FSM infrastructure.
+ *
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno flow_fsm_init(void)
+{
+ int ii;
+ flow_inst *new_entry;
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifdef ENABLE_LOG
+ log_id_flow = bcm_dev_log_id_register("FLOW", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_flow == DEV_LOG_INVALID_ID);
+#endif
+
+ /* Initialize all of the flow queues */
+ TAILQ_INIT(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list);
+ TAILQ_INIT(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list);
+
+ /* Populate the free list with it's initial set of flows
+ */
+ for(ii=0; ii<FLOW_ALLOCATION_BLOCK_SIZE; ii++)
+ {
+
+ new_entry = bcmos_calloc(sizeof(flow_inst));
+
+ if (NULL == new_entry)
+ {
+ BCM_LOG(FATAL, log_id_flow, "Failed to initialize the flow free list - FATAL\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ flow_free_by_entry(new_entry);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to un-initialize the Flow FSM infrastructure.
+ *
+ * NOTE: This is called once on shutdown and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno flow_fsm_finish(void)
+{
+
+ flow_inst *current_entry, *p_temp_entry;
+
+ /* Free all the entries on the active list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
+
+ bcmos_free(current_entry);
+
+ }
+
+ /* Free all the entries on the free list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list,
+ flow_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, current_entry, flow_inst_next);
+
+ bcmos_free(current_entry);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing executive function
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param p_event Pointer to a flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_exec(flow_inst *p_flow_inst, flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ flow_fsm_state pre_state;
+ flow_fsm_state_processor flow_state_processor;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_flow_inst);
+ BUG_ON(NULL == p_event);
+
+ /* Record the present state for debug printing
+ */
+ pre_state = p_flow_inst->fsm_state;
+
+ /*
+ * Get the state processing function
+ */
+ flow_state_processor = flow_states[p_flow_inst->fsm_state][p_event->event_type];
+
+ /*
+ * If there's a state processing function for this event and state, execute it.
+ * Otherwise, process a generic error.
+ */
+ if (flow_state_processor)
+ {
+ ret = flow_state_processor(p_flow_inst, p_event->msg, p_event);
+ } else
+ {
+ flow_fsm_state_err(p_flow_inst, p_event->msg, p_event);
+ }
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_flow, "*** Error detected during state processing\n");
+ p_flow_inst->fsm_state = pre_state;
+ }
+
+ BCM_LOG(DEBUG, log_id_flow, "*** Event %s, State: %s --> %s\n\n",
+ flow_event_name_get(p_event->event_type),
+ flow_state_name_get(pre_state),
+ flow_state_name_get(p_flow_inst->fsm_state));
+
+ return ret;
+}
+
+
+
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing for a flow admin-up command received
+ * from the BAL Public API when the specified flow instance is in the
+ * admin-down state (i.e. when the flow instance FSM is in the NULL state).
+ *
+ * @param p_flow_inst Pointer to an flow instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_admin_up_start(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmos_bool is_ds_flow_to_host, is_ds_n_to_1;
+
+
+ BCM_LOG(INFO, log_id_flow, "Got admin UP request from BAL API - bringing up FLOW\n");
+
+ do
+ {
+ /* change Flow state to CONFIGURING */
+ p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Switch Utils to add applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_ADD)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "error %s detected by switch util while adding flow\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*– Core calls Mac Utils add applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_ADD)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "error %s detected by mac util\n", bcmos_strerror(ret));
+
+ /* Remove the (just added) flow from the switch otherwise the switch utils
+ * will remember it and complain when this flow is added later. There's not
+ * much we can do about it if removing this flow fails.
+ */
+ if(BCM_ERR_OK != sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_CLEAR))
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "error detected by switch util while removing flow\n");
+ }
+
+ break;
+ }
+
+ /* The hardware has properly accepted the object info, so the request object becomes
+ * the current state.
+ */
+ bcmbal_flow_object_overlay_w_src_priority(&p_flow_inst->current_flow_info,
+ &p_flow_inst->api_req_flow_info);
+
+ is_ds_flow_to_host = (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type &&
+ (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, action) &&
+ (p_flow_inst->api_req_flow_info.data.action.cmds_bitmask &
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)));
+
+ is_ds_n_to_1 = ((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) &&
+ (BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, group_id) ));
+
+
+ /* Add the svc_port_id record to the sub_term record for upstream flows,
+ * or for downstream flows that are not destined to the host
+ */
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type ||
+ (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type &&
+ !(is_ds_flow_to_host) && !(is_ds_n_to_1)))
+
+ {
+ bcmbal_sub_term_svc_port_id_list_entry_add(p_flow_inst->p_sub_term_inst,
+ p_flow_inst->api_req_flow_info.data.svc_port_id);
+ }
+
+ /* Add the agg_port_id to the sub_term record (only for upstream flows) */
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
+ {
+ bcmbal_sub_term_agg_port_id_list_entry_add(p_flow_inst->p_sub_term_inst,
+ p_flow_inst->api_req_flow_info.data.agg_port_id);
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* If there were errors during processing, then report the error to the API and free the flow */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_flow);
+
+ flow_free_by_entry(p_flow_inst);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing for a flow admin-up command received
+ * from the BAL Public API when the specified flow FSM is already
+ * in the REMOVING state.
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_admin_up_error(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_STATE;
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Received an admin UP request from BAL API"
+ " - returning ERROR to the API - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing for a flow admin-down command
+ * received from the BAL Public API when the specified flow is
+ * admin-up (i.e when the specified flow instance FSM is in the
+ * CONFIGURED state).
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_admin_dn_start(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_flow,
+ "Got admin DOWN request from BAL API - bringing down FLOW\n");
+
+ /* change Flow state to CONFIGURING */
+ p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURING;
+
+ do
+ {
+ /*– Core calls Switch Utils to remove applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_REMOVE)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "error %s detected by switch util\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*– Core calls Mac Utils remove applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_REMOVE)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "error %s detected by mac util\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /* The hardware has properly accepted the object info but we do
+ * not overwrite the current flow data as there is nothing in the request
+ * that is relevant besides the admin_state
+ */
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_TRUE);
+
+ }while(0);
+ /* Report any error found to the API immediately */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_flow);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing for a flow clear command
+ * received from the BAL Public API.
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_clear_start(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *p_tm_sched_inst;
+ uint32_t alloc_ref_count;
+ bcmos_bool b_flow_is_destined_to_host;
+ tm_queue_inst *p_tm_queue_inst = NULL;
+
+ BCM_LOG(INFO, log_id_flow,
+ "Got CLEAR request from BAL API - removing FLOW\n");
+
+ /* change Flow state to REMOVING */
+ p_flow_inst->fsm_state = FLOW_FSM_STATE_REMOVING;
+
+
+ b_flow_is_destined_to_host = ((BCMBAL_CFG_PROP_IS_SET(&(p_flow_inst->api_req_flow_info), flow, action) &&
+ (p_flow_inst->api_req_flow_info.data.action.cmds_bitmask &
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE);
+ do
+ {
+ /*Core calls Switch Utils to clear applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_CLEAR)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "error %s detected by switch util\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*Core calls Mac Utils clear applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_flow_set(p_flow_inst, BAL_UTIL_OPER_FLOW_CLEAR)))
+ {
+ /* if entry does not exist for a clear, that is fine, since anyway that would have been the end goal */
+ if (BCM_ERR_NOENT != ret)
+ {
+ BCM_LOG(ERROR, log_id_flow, "error %s detected by mac util\n", bcmos_strerror(ret));
+ break;
+ }
+ }
+
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
+ {
+ /*handle the alloc id and alloc - tm sched*/
+ if(BCM_ERR_OK != rsc_mgr_alloc_id_free(p_flow_inst->api_req_flow_info.data.access_int_id,
+ p_flow_inst->api_req_flow_info.data.agg_port_id, p_flow_inst))
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ " error encountered during release of flow resources (agg_port_id: %d, intf_id:%d\n",
+ p_flow_inst->api_req_flow_info.data.access_int_id,
+ p_flow_inst->api_req_flow_info.data.agg_port_id);
+ }
+ /*check if tm sched should be removed - ref count = 1 and tm sched is auto created*/
+ if(BCM_ERR_OK != (ret = flow_tm_get(&(p_flow_inst->api_req_flow_info), &p_tm_sched_inst)))
+ {
+
+ BCM_LOG(ERROR, log_id_flow,
+ " could not find tm sched for agg_port_id: %d, intf_id:%d\n",
+ p_flow_inst->api_req_flow_info.data.access_int_id,
+ p_flow_inst->api_req_flow_info.data.agg_port_id);
+ break;
+ }
+ ret = rsc_mgr_alloc_id_get_ref_count(p_flow_inst->api_req_flow_info.data.access_int_id,p_flow_inst->api_req_flow_info.data.agg_port_id, &alloc_ref_count);
+
+ if(BCM_ERR_OK == ret
+ && BCMBAL_TM_CREATION_MODE_AUTO == p_tm_sched_inst->req_tm_sched_info.data.creation_mode
+ && 1 == alloc_ref_count)
+ {
+ ret = bcmbal_tm_sched_fsm_active_destroy(p_tm_sched_inst);
+ }
+ }
+
+ /*if the flow is not a cpu flow (to host), should handle it sched/queue setting*/
+ if(!b_flow_is_destined_to_host)
+ {
+ /*remove the flow from the the tm queue list*/
+ /*find tm queue instance*/
+ ret = flow_queue_validate(&p_flow_inst->api_req_flow_info, &p_tm_queue_inst);
+
+ if (ret != BCM_ERR_OK)
+ {
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ ret = bcmbal_tm_queue_use_set(p_tm_queue_inst, BCMOS_FALSE);
+ if (ret != BCM_ERR_OK)
+ {
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ /* The hardware has properly accepted the object info, so the request object becomes
+ * the current state, except for the oper_status.
+ */
+ bcmbal_flow_object_overlay_w_src_priority(&p_flow_inst->current_flow_info,
+ &p_flow_inst->api_req_flow_info);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* Report any error found to the API immediately */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_flow);
+ }
+
+ return ret;
+
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing for a flow admin-down command
+ * from the BAL Public API when the specified flow is already
+ * admin-down.
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_admin_dn_ok(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Received an admin DOWN request from BAL API"
+ " - returning OK to the API - no further function\n");
+
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_flow);
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing for a flow admin-down command
+ * received from the BAL Public API when the specified flow FSM
+ * is in the CONFIGURING state.
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_admin_dn_error(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_STATE;
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Received an admin DOWN request from BAL API"
+ " - returning ERROR to the API - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing function to ignore a received message.
+ *
+ * @param p_flow_inst Pointer to an flow instance
+ * @param msg Pointer to a BAL message received from the BAL utils
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_ignore_util_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_flow, "Ignoring message from BAL utils\n");
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing function to process an AUTO IND
+ * message from one of the BAL apps.
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to a flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_null_process_util_auto_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_flow_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(DEBUG, log_id_flow, "Received an AUTO IND in the NULL state\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing function to process a message from
+ * one of the BAL apps received when the specified flow instance FSM
+ * is in the CONFIGURING state.
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_process_util_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_flow_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+
+ BCM_LOG(DEBUG, log_id_flow,
+ " Received an IND message from BAL UTIL (%s) during %s state\n",
+ subsystem_str[bcmbal_sender_get(msg)],flow_state_name_get(p_flow_inst->fsm_state));
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "%s, thread %s, module %d\n", __FUNCTION__, bcmos_task_current()->name, bcmos_module_current());
+
+ /* Handle indication */
+ ret = ind_msg->status;
+
+ /* Reflect the execution status in the object being returned in the indication
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ p_flow_inst->current_flow_info.data.oper_status =
+ p_flow_inst->api_req_flow_info.data.oper_status;
+
+ /*
+ * The flow has been successfully configured
+ */
+ p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURED;
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_flow, "Flow %d: Failed in state %s. Error %s\n",
+ p_flow_inst->api_req_flow_info.key.flow_id,
+ flow_state_name_get(p_flow_inst->fsm_state),
+ bcmos_strerror(ret));
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_FALSE);
+ p_flow_inst->current_flow_info.hdr.hdr.status = ret;
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_flow_inst->current_flow_info.hdr,
+ log_id_flow);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing function to process a message from
+ * one of the BAL apps received
+ *
+ * @param p_flow_inst Pointer to a flow instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an access terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_process_util_auto_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bal_util_msg_auto_ind *ind_msg;
+
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_flow_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Received an AUTO IND message in the %s state\n",
+ flow_state_name_get(p_flow_inst->fsm_state));
+
+ ind_msg = (bal_util_msg_auto_ind *)msg;
+
+ /* Handle indication */
+ ret = ind_msg->status;
+
+ if(BCM_ERR_OK == ret)
+ {
+ /* data reflects the new oper_status in the object being indicated */
+ memcpy(&p_flow_inst->current_flow_info.data.oper_status, ind_msg->data, sizeof(bcmbal_status));
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_flow_inst->current_flow_info.hdr,
+ log_id_flow);
+
+
+ p_flow_inst->fsm_state = FLOW_FSM_STATE_CONFIGURED;
+
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing function to process a
+ * message from one of the BAL apps received when the specified
+ * flow instance FSM is in the REMOVING state.
+ *
+ * @param p_flow_inst Pointer to an flow instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_removing_process_util_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bal_util_msg_ind *ind_msg;
+ bcmos_bool is_ds_flow_to_host;
+ /* Parameter checks */
+ BUG_ON(NULL == p_flow_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+
+ BCM_LOG(DEBUG, log_id_flow,
+ " Received an IND message from BAL UTIL (%s) during REMOVING state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ do{
+
+ /* Handle indication */
+ ret = ind_msg->status;
+
+ /* Reflect the execution status in the object being returned in the indication
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type ||
+ BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
+ {
+ is_ds_flow_to_host = (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type &&
+ (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, action) &&
+ (p_flow_inst->api_req_flow_info.data.action.cmds_bitmask &
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)));
+
+ if (bcm_topo_pon_get_pon_family(p_flow_inst->api_req_flow_info.data.access_int_id) == BCM_TOPO_PON_FAMILY_GPON)
+ {
+
+ /* Don't attempt to release a GEM for a downstream flow that is TRAP_TO_HOST, because there
+ * is no subscriber terminal involved in this flow (there was no GEM allocated for this flow).
+ */
+ if(BCMOS_FALSE == is_ds_flow_to_host)
+ {
+ if(BCM_ERR_OK != rsc_mgr_gem_free(p_flow_inst->api_req_flow_info.data.access_int_id,
+ p_flow_inst->api_req_flow_info.data.svc_port_id, p_flow_inst))
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ " error encountered during release of flow resources (svc_port_id: %d, intf_id:%d\n",
+ p_flow_inst->api_req_flow_info.data.svc_port_id,
+ p_flow_inst->api_req_flow_info.data.access_int_id);
+ }
+ }
+
+
+ }
+
+ /* Remove the svc_port_id record from the sub_term record for upstream flows,
+ * or for downstream flows that are not destined to the host
+ */
+ if((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) ||
+ ((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) &&
+ !(is_ds_flow_to_host)))
+ {
+ bcmbal_sub_term_svc_port_id_list_entry_remove(p_flow_inst->p_sub_term_inst,
+ p_flow_inst->current_flow_info.data.svc_port_id);
+ }
+
+ /* Remove the agg_port_id from the sub_term record (only for upstream flows) */
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
+ {
+
+ bcmbal_sub_term_agg_port_id_list_entry_remove(p_flow_inst->p_sub_term_inst,
+ p_flow_inst->current_flow_info.data.agg_port_id);
+ }
+ }
+
+ p_flow_inst->current_flow_info.hdr.hdr.status = ret;
+
+ /* This is the proper state and status for the indication about to be sent */
+ p_flow_inst->current_flow_info.data.admin_state = BCMBAL_STATE_DOWN;
+ p_flow_inst->current_flow_info.data.oper_status = BCMBAL_STATUS_DOWN;
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_flow_inst->current_flow_info), BCMOS_FALSE);
+
+ /*
+ * Send the success indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_flow_inst->current_flow_info.hdr,
+ log_id_flow);
+
+ /* Return the flow to the free pool regardless of the errors encountered above */
+ flow_free_by_entry(p_flow_inst);
+ }
+ else
+ {
+ /*
+ * Send the failure indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_flow_inst->current_flow_info.hdr,
+ log_id_flow);
+ }
+ }while(0);
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM state processing function to process a
+ * AUTO IND message from one of the BAL apps received when the specified
+ * flow instance FSM is in the REMOVING state.
+ *
+ * @param p_flow_inst Pointer to an flow instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_removing_process_util_auto_msg(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_flow_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Received an AUTO IND in the removing state"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Flow FSM function which is executed when an error
+ * is encountered during FSM processing.
+ *
+ * @param p_flow_inst Pointer to an flow instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an flow event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_fsm_state_err(flow_inst *p_flow_inst,
+ void *msg,
+ flow_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_INVALID_OP;
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Error encountered processing FLOW FSM"
+ " - BAD EVENT ()\n");
+
+ return ret;
+}
+static bcmos_errno flow_queue_validate(bcmbal_flow_cfg *p_flow_cfg, tm_queue_inst **p_tm_queue_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_interface_key intf_key;
+ bcmbal_tm_sched_key tm_key;
+ tm_sched_inst *p_tm_sched;
+ bcmbal_tm_queue_key queue_key;
+ bcmbal_tm_queue_ref queue_ref;
+ bcmos_bool is_auto_set = BCMOS_TRUE;
+
+ do
+ {
+ if (BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_cfg->key.flow_type)
+ {
+ intf_key.intf_type = BCMBAL_INTF_TYPE_NNI;
+ tm_key.dir = BCMBAL_TM_SCHED_DIR_US;
+ intf_key.intf_id = p_flow_cfg->data.network_int_id;
+ }
+ else /*BCMBAL_FLOW_TYPE_DOWNSTREM or BCMBAL_FLOW_TYPE_MULTICAST */
+ {
+ intf_key.intf_type = BCMBAL_INTF_TYPE_PON;
+ tm_key.dir = BCMBAL_TM_SCHED_DIR_DS;
+ intf_key.intf_id = p_flow_cfg->data.access_int_id;
+ }
+
+ if (BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, queue))
+ {
+ queue_ref = p_flow_cfg->data.queue;
+ is_auto_set = BCMOS_FALSE;
+ }
+ else
+ {
+ /*look for the auto created tm sched and queue*/
+ ret = bcmbal_interface_tm_get(intf_key, &tm_key.id);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "could not get interface instance"
+ " to set flow queue reference intf_key.intf_type = %d,"
+ " intf_key.intf_id = %d\n",
+ intf_key.intf_type, intf_key.intf_id);
+ break;
+ }
+ p_tm_sched = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "could not get tm sched instance to "
+ "set flow queue reference intf_key.intf_type = %d,"
+ " intf_key.intf_id = %d tm_key.dir = %s\n"
+ ,intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ if(BCMBAL_TM_CREATION_MODE_AUTO != p_tm_sched->current_tm_sched_info.data.creation_mode)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "can not set flow queue reference if the "
+ "interface tm sched is not auto created. "
+ "intf_key.intf_type = %d, intf_key.intf_id = %d tm_key.dir = %s\n",
+ intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /*if the tm sched exist and it is auto created, queue 0 should be there as well*/
+ queue_ref.sched_id = tm_key.id;
+ queue_ref.queue_id = 0;
+ BCM_LOG(INFO, log_id_flow,
+ "flow will be assign to queue: node id=%d "
+ "node dir=%s queue id = %d\n",
+ tm_key.id, TM_SCHED_DIR_TO_STR(tm_key.dir), queue_ref.queue_id);
+
+ BCMBAL_CFG_PROP_SET(p_flow_cfg, flow, queue, queue_ref);
+ }
+
+ queue_key.id = queue_ref.queue_id;
+ queue_key.sched_id = queue_ref.sched_id;
+ queue_key.sched_dir = tm_key.dir;
+
+ /*validate a given tm queue exist and match flow type*/
+ *p_tm_queue_inst = tm_queue_inst_get(queue_key, TM_QUEUE_FLAG_ACTIVE);
+ if (NULL == *p_tm_queue_inst)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "could not find the queue to assign the flow to "
+ ":tm sched dir = %s tm sched id = %d queue id = %d\n",
+ TM_SCHED_DIR_TO_STR(queue_key.sched_dir), queue_key.sched_id,queue_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ if (BCMOS_FALSE == is_auto_set)
+ {
+ /*should validate queue is related to the flow intf/sub_term/sub_term_uni*/
+ tm_key.dir = queue_key.sched_dir;
+ tm_key.id = queue_key.sched_id;
+
+ p_tm_sched = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "could not get tm sched instance to set flow queue "
+ "reference intf_key.intf_type = %d, intf_key.intf_id = %d tm_key.dir = %s\n",
+ intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched->req_tm_sched_info,tm_sched,owner))
+ {
+ switch(p_tm_sched->req_tm_sched_info.data.owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ {
+ if (p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.intf_id != p_flow_cfg->data.access_int_id
+ || p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.sub_term_id!= p_flow_cfg->data.sub_term_id)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "queue referenced by flow, attached to tm sched instance that is owned by "
+ "sub term intf_id = %d sub_term_id = %d while flow is related to sub term"
+ " intf_id = %d sub_term_id = %d therefor cannot be set as flow queue\n",
+ p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.intf_id,
+ p_tm_sched->req_tm_sched_info.data.owner.u.sub_term.sub_term_id,
+ p_flow_cfg->data.access_int_id,
+ p_flow_cfg->data.sub_term_uni_idx);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ if (p_tm_sched->req_tm_sched_info.data.owner.u.uni.intf_id != p_flow_cfg->data.access_int_id
+ || p_tm_sched->req_tm_sched_info.data.owner.u.uni.sub_term_id!= p_flow_cfg->data.sub_term_id
+ || p_tm_sched->req_tm_sched_info.data.owner.u.uni.idx != p_flow_cfg->data.sub_term_uni_idx)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "queue referenced by flow , attached to tm sched "
+ "instance that is owned by sub term uni intf_id = %d "
+ "sub_term_id = %d uni = %d while flow is related to uni sub "
+ "term intf_id = %d sub_term_id = %d uni = %d therefor cannot be "
+ "set as flow queue\n",
+ p_tm_sched->req_tm_sched_info.data.owner.u.uni.intf_id,
+ p_tm_sched->req_tm_sched_info.data.owner.u.uni.sub_term_id,
+ p_tm_sched->req_tm_sched_info.data.owner.u.uni.idx,
+ p_flow_cfg->data.access_int_id,
+ p_flow_cfg->data.sub_term_id,
+ p_flow_cfg->data.sub_term_uni_idx);
+ ret = BCM_ERR_PARM;
+ }
+ }
+ break;
+ default:
+ BCM_LOG(ERROR, log_id_flow,
+ "tm sched instance is owned by %d therefor "
+ "cannot be set as flow queue\n",
+ p_tm_sched->req_tm_sched_info.data.owner.type);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "tm sched instance is not set with an owner therefor "
+ "cannot be set as flow queue intf_key.intf_type = %d, "
+ "intf_key.intf_id = %d tm_key.dir = %s\n",
+ intf_key.intf_type, intf_key.intf_id, TM_SCHED_DIR_TO_STR(tm_key.dir));
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ }while (0);
+ return ret;
+
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function called by the core worker thread to process an
+ * flow object message (SET, GET, CLEAR, STATS) received
+ * from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_flow_object(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
+ bcmbal_flow_cfg *p_flow_cfg = (bcmbal_flow_cfg *)msg_payload;
+ flow_inst *p_flow_inst = NULL;
+ flow_fsm_event fsm_event;
+ bcmbal_flow_key *p_flow_key;
+ bcmbal_state admin_state_req;
+ bcmos_bool b_flow_is_destined_to_host;
+ bcmbal_obj_msg_type oper_type;
+ bcmbal_subscriber_terminal_key sub_term_key;
+ sub_term_inst *p_sub_term_inst = NULL;
+ bcmos_bool is_multicast = BCMOS_FALSE;
+ bcmos_bool is_unicast = BCMOS_FALSE;
+
+ bcmos_bool is_us_n_to_1 = BCMOS_FALSE;
+ bcmos_bool is_ds_n_to_1 = BCMOS_FALSE;
+
+ tm_queue_inst *p_tm_queue_inst = NULL;
+
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id_flow, "Processing a flow object\n");
+
+ p_flow_key = &p_flow_cfg->key;
+
+ oper_type = p_flow_cfg->hdr.hdr.type;
+
+ is_multicast = (BCMBAL_FLOW_TYPE_MULTICAST == p_flow_key->flow_type);
+
+ is_unicast = ((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_key->flow_type) ||
+ (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_key->flow_type));
+
+ is_us_n_to_1 = ((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_key->flow_type) &&
+ (BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, group_id)));
+
+ is_ds_n_to_1 = ((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_key->flow_type) &&
+ (BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, group_id) ));
+
+
+ /*
+ * A message pointer may be passed inside the event structure.
+ */
+ fsm_event.msg = msg_payload;
+
+ /* SET or GET or CLEAR...? */
+ switch (oper_type)
+ {
+ case (BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+ bcmos_bool b_generate_event = BCMOS_FALSE;
+ bcmos_bool found_new_flow = BCMOS_FALSE;
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Processing a flow SET REQ mgmt message\n");
+
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ b_flow_is_destined_to_host = ((BCMBAL_CFG_PROP_IS_SET(p_flow_cfg, flow, action) &&
+ (p_flow_cfg->data.action.cmds_bitmask &
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE);
+
+ admin_state_req = p_flow_cfg->data.admin_state;
+
+ BCM_LOG(INFO, log_id_flow,
+ "flow %d:%s request - admin state requested is %s\n",
+ p_flow_key->flow_id,
+ CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type),
+ (BCMBAL_STATE_UP == admin_state_req) ? "UP" : "DOWN");
+
+ /*
+ * Find or create the specified flow instance
+ */
+ p_flow_inst = flow_inst_get(p_flow_key, FLOW_FLAG_ANY, &found_new_flow);
+ if(NULL == p_flow_inst)
+ {
+ /* This is a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_flow,
+ "ERROR - Flow not found. No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ /*
+ * Fill in the local flow info data structure
+ */
+ p_flow_inst->api_req_flow_info = *p_flow_cfg;
+
+ /* For flows that have already been configured, merge the
+ * requested flow data with the current flow data, and this results in the new request.
+ */
+ if((BCMOS_FALSE == found_new_flow) &&
+ (p_flow_inst->api_req_flow_info.data.oper_status != p_flow_inst->current_flow_info.data.oper_status))
+ {
+ bcmbal_flow_object_overlay_w_dst_priority(&p_flow_inst->api_req_flow_info,
+ &p_flow_inst->current_flow_info);
+ }
+
+ BCM_LOG(INFO, log_id_flow,
+ "flow access_int_id: %d, sub_term_id: %d\n",
+ p_flow_inst->api_req_flow_info.data.access_int_id,
+ p_flow_inst->api_req_flow_info.data.sub_term_id);
+
+ /* Next, find sub term instance, if is flow UP */
+ if (BCMBAL_STATE_UP == admin_state_req)
+ {
+ sub_term_key.intf_id = p_flow_inst->api_req_flow_info.data.access_int_id;
+ sub_term_key.sub_term_id = p_flow_inst->api_req_flow_info.data.sub_term_id;
+
+ p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
+
+ if (!p_sub_term_inst && !is_multicast && !is_ds_n_to_1 && !b_flow_is_destined_to_host)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "No active subscriber terminal with id=%u, and for flow type %s \n",
+ sub_term_key.sub_term_id,
+ CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type));
+
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /*if the flow is not a cpu flow (to host), then we should validate/use the sched/queue setting*/
+ if(!b_flow_is_destined_to_host)
+ {
+ /*find tm queue instance*/
+ ret = flow_queue_validate(&(p_flow_inst->api_req_flow_info), &p_tm_queue_inst);
+ if (ret != BCM_ERR_OK)
+ {
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ ret = bcmbal_tm_queue_use_set(p_tm_queue_inst, BCMOS_TRUE);
+ if (ret != BCM_ERR_OK)
+ {
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ }
+
+ p_flow_inst->p_sub_term_inst = p_sub_term_inst;
+
+ /*
+ * Process the request
+ */
+ if(((BCMBAL_STATE_UP == admin_state_req) || found_new_flow)
+ && (BCMBAL_STATE_UP != p_flow_inst->current_flow_info.data.admin_state))
+ {
+ bcmbal_service_port_id svc_port_id = 0;
+ flow_inst *p_peer_flow;
+ uint8_t svc_port_id_range;
+
+ do
+ {
+ if (bcm_topo_pon_get_pon_family(p_flow_inst->api_req_flow_info.data.access_int_id) == BCM_TOPO_PON_FAMILY_GPON)
+ {
+ /* There's no need to do anything with the MAC in downstream flows that
+ * that are destined to the host CPU (i.e. NNI->CPU)
+ */
+ if((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) ||
+ !(b_flow_is_destined_to_host))
+ {
+
+ /*
+ * GEM resolution does not rely on the pbits in a packet, however,
+ * we currently only support allocate a svc_port_id range of 1.
+ */
+ svc_port_id_range = 1;
+
+ /* Is there a peer flow configured already? (only upstream and downstream flows
+ * can have a peer flow)
+ * If not, look in the active list for a match. NOTE: It might not be there.
+ */
+ if( is_unicast && NULL == p_flow_inst->p_peer_flow_inst)
+ {
+ /*
+ * See if we can find a peer flow (a peer flow is a flow that has
+ * the same flow ID as this flow does, but has the opposite direction
+ * in the key).
+ */
+
+ /* Look for an active flow, but ignore the direction (BEWARE: we might
+ * find ourself!!)
+ */
+ p_peer_flow = flow_inst_get(p_flow_key,
+ FLOW_FLAG_ACTIVE | FLOW_FLAG_IGNORE_DIR,
+ NULL);
+
+ /* If the flow that we found isn't us, then link it to our flow
+ */
+ if(p_peer_flow->api_req_flow_info.key.flow_type !=
+ p_flow_inst->api_req_flow_info.key.flow_type)
+ {
+ p_flow_inst->p_peer_flow_inst = p_peer_flow;
+ }
+ }
+
+ /* If a peer flow exists, copy the GEM ID from the peer flow into this flow
+ */
+ if(NULL != p_flow_inst->p_peer_flow_inst)
+ {
+ svc_port_id =
+ p_flow_inst->p_peer_flow_inst->current_flow_info.data.svc_port_id;
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Using GEM ID from peer flow (%d) on access_id %d\n",
+ svc_port_id,
+ p_flow_inst->api_req_flow_info.data.access_int_id);
+
+ /* even though we have gem Id, get it allocated by rsrc mgr so that it can
+ * manage ref counts.
+ */
+ ret = rsc_mgr_gem_alloc_unicast(
+ p_flow_inst->api_req_flow_info.data.access_int_id,
+ &svc_port_id,
+ svc_port_id_range,
+ p_flow_inst); /* A multicast flow cannot have a peer flow. So this means this is definitely not a multicast. */
+ if (BCM_ERR_OK != ret)
+ {
+ /*
+ * An error has occurred trying to get mandatory data
+ */
+
+ BCM_LOG(ERROR, log_id_flow, "Failed to get base GEM from resource manager\n");
+
+ /*
+ * @todo If the flow instance (that we got) is not active, then return it to the
+ * free pool.
+ */
+
+ break;
+ }
+ }
+ else /* A peer flow does not exist */
+ {
+ /* needs single GEM for flows which is not multicast and not downstream N:1 service.
+ In another words, all upstream flows and downstream flows which is not N:1 service needs one GEM */
+ if(!is_multicast && !is_ds_n_to_1)
+ {
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info,
+ flow,
+ svc_port_id))
+ {
+ svc_port_id = p_flow_inst->api_req_flow_info.data.svc_port_id;
+
+
+ BCM_LOG(DEBUG, log_id_flow,
+ "Using the base GEM ID supplied by the user (%d) on access_id %d\n",
+ svc_port_id,
+ p_flow_inst->api_req_flow_info.data.access_int_id);
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_flow,
+ "Getting a new base GEM ID on access_id %d from resource manager\n",
+ p_flow_inst->api_req_flow_info.data.access_int_id);
+ svc_port_id = 0; /* 0 is a magic number telling the resource manager that it should provide
+ * the initial allocation of the base GEM */
+ }
+
+ ret = rsc_mgr_gem_alloc_unicast(p_flow_inst->api_req_flow_info.data.access_int_id,
+ &svc_port_id,
+ svc_port_id_range,
+ p_flow_inst);
+
+ if (BCM_ERR_OK != ret)
+ {
+ /*
+ * An error has occurred trying to get mandatory data
+ */
+
+ BCM_LOG(ERROR, log_id_flow, "Failed to get base GEM from resource manager\n");
+
+ /*
+ * @todo If the flow instance (that we got) is not active, then return it to the
+ * free pool.
+ */
+
+ break;
+ }
+ }
+ /* make sure the all members in the group assoficated with the flow has a GEM */
+ if(BCMBAL_CFG_PROP_IS_SET(&p_flow_inst->api_req_flow_info, flow, group_id))
+ {
+ bcmbal_group_key group_key;
+ bcmbal_group_owner group_owner;
+
+ group_key.group_id = p_flow_inst->api_req_flow_info.data.group_id;
+ if(is_ds_n_to_1 || is_us_n_to_1 )
+ {
+ group_owner = BCMBAL_GROUP_OWNER_UNICAST;
+ }
+ else
+ {
+ group_owner = BCMBAL_GROUP_OWNER_MULTICAST;
+ }
+
+ ret = group_owner_set(group_key, group_owner);
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "error %s while updating group owner\n", bcmos_strerror(ret));
+ break;
+ }
+ }
+ }
+ /*
+ * Set the GEM ID into the object being processed
+ */
+ if(svc_port_id)
+ {
+ BCMBAL_CFG_PROP_SET(&p_flow_inst->api_req_flow_info, flow, svc_port_id,svc_port_id);
+ BCM_LOG(DEBUG, log_id_flow, "GEM %d being used\n", svc_port_id);
+ }
+ /*
+ * alloc ID is only required on an UPSTREAM FLOW
+ */
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type)
+ {
+ tm_sched_inst * dummy_p_tm_sched_inst;
+ ret = flow_tm_get(&p_flow_inst->api_req_flow_info, &dummy_p_tm_sched_inst);
+
+ if (BCM_ERR_OK != ret)
+ {
+ /* An error has occurred trying to get mandatory data */
+ BCM_LOG(ERROR, log_id_flow, "Failed to get required tm sched for agg port id\n");
+ break;
+ }
+ ret = rsc_mgr_alloc_id_alloc( p_flow_inst->api_req_flow_info.data.access_int_id,
+ &p_flow_inst->api_req_flow_info.data.agg_port_id, 1, p_flow_inst);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_flow, "Failed to get ALLOC ID from resource manager\n");
+ break;
+ }
+
+ BCM_LOG(DEBUG, log_id_flow, "ALLOC ID %d being used\n", p_flow_inst->api_req_flow_info.data.agg_port_id);
+ }
+
+ /*
+ * Perform the validation check(s) that the utils require
+ */
+ if(BCM_ERR_OK != (ret = mac_util_flow_info_validate(&p_flow_inst->api_req_flow_info)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "Failed mac validation\n");
+ break;
+ }
+ }
+ }
+ else if (bcm_topo_pon_get_pon_family(p_flow_inst->api_req_flow_info.data.access_int_id) == BCM_TOPO_PON_FAMILY_EPON)
+ {
+ /* There's no need to do anything with the MAC in downstream flows that
+ * that are destined to the host CPU (i.e. NNI->CPU)
+ */
+ if((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) ||
+ !(b_flow_is_destined_to_host))
+ {
+
+ sub_term_key.intf_id = p_flow_inst->api_req_flow_info.data.access_int_id;
+ sub_term_key.sub_term_id = p_flow_inst->api_req_flow_info.data.sub_term_id;
+
+ p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
+
+ if (!p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "Failed to get subscriber terminal with id=%u\n",
+ sub_term_key.sub_term_id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ /*
+ * set svc_port to the subtunnel id.
+ */
+ BCMBAL_CFG_PROP_SET(&p_flow_inst->api_req_flow_info, flow,
+ svc_port_id,p_sub_term_inst->current_sub_term_info.data.svc_port_id);
+
+ /*
+ * Perform the validation check(s) that the utils require
+ */
+ if(BCM_ERR_OK != (ret = mac_util_flow_info_validate(&p_flow_inst->api_req_flow_info)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "Failed mac validation\n");
+ break;
+ }
+ }
+ }
+
+ /* No need to do anything in the switch for upstream flows that
+ * that are destined to the host CPU (i.e. PON->CPU), so no switch
+ * validation is necessary.
+ */
+ if(!((BCMBAL_FLOW_TYPE_UPSTREAM == p_flow_inst->api_req_flow_info.key.flow_type) &&
+ b_flow_is_destined_to_host))
+ {
+ if(BCM_ERR_OK != (ret = sw_util_flow_info_validate(&p_flow_inst->api_req_flow_info)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "Failed switch validation\n");
+ break;
+ }
+ }
+
+ p_flow_inst->current_flow_info.data.admin_state = BCMBAL_STATE_UP;
+
+ /* Set the expected state of the oper_status upon success */
+ p_flow_inst->api_req_flow_info.data.oper_status = BCMBAL_STATUS_UP;
+
+ fsm_event.event_type = FLOW_FSM_EVENT_TYPE_ADMIN_UP;
+ b_generate_event = BCMOS_TRUE;
+
+ } while(0);
+
+ if(BCM_ERR_OK != ret)
+ {
+ flow_free_by_entry(p_flow_inst);
+ break;
+ }
+ }
+ /*
+ * NOTE: This is not a complete implementation of the admin down processing.
+ *
+ * @todo - complete admin down processing
+ */
+ else if(((BCMBAL_STATE_DOWN == admin_state_req) || found_new_flow)
+ && (BCMBAL_STATE_DOWN != p_flow_inst->current_flow_info.data.admin_state))
+ {
+ p_flow_inst->current_flow_info.data.admin_state = BCMBAL_STATE_DOWN;
+
+ /* Set the expected state of the oper_status upon success */
+ p_flow_inst->api_req_flow_info.data.oper_status = BCMBAL_STATUS_DOWN;
+
+ fsm_event.event_type = FLOW_FSM_EVENT_TYPE_ADMIN_DN;
+ b_generate_event = BCMOS_TRUE;
+ }
+ else
+ {
+ /* @todo implement a MODIFY here */
+
+ break; /* no state change detected - do nothing for now */
+ }
+
+ }while(0);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
+
+ if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
+ {
+ /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
+ ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
+ break;
+ }
+
+ /* If there was an event generated, call the state machine exec */
+ if(BCMOS_TRUE == b_generate_event)
+ {
+ /*
+ * Run the flow FSM to process this event
+ */
+ ret = flow_fsm_exec(p_flow_inst, &fsm_event);
+ }
+ break;
+ }
+
+ case (BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+
+ BCM_LOG(DEBUG, log_id_flow, "Processing a flow GET REQ mgmt message\n");
+
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ }
+ else
+ {
+ /*
+ * Find the specified flow instance
+ */
+ p_flow_inst = flow_inst_get(p_flow_key, FLOW_FLAG_ACTIVE, NULL);
+ }
+
+ if(NULL == p_flow_inst)
+ {
+ if(BCM_ERR_STATE != ret)
+ {
+ /* This is not a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_flow, "ERROR - Specified flow (%d:%s) not found\n",
+ p_flow_key->flow_id,
+ CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type));
+ ret = BCM_ERR_NOENT;
+ }
+
+ break;
+ }
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ p_flow_inst->current_flow_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+ *((bcmbal_flow_cfg *)msg_payload) = p_flow_inst->current_flow_info;
+
+ } while (0);
+
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
+
+ }
+ break;
+
+ case (BCMBAL_OBJ_MSG_TYPE_CLEAR):
+ {
+ BCM_LOG(DEBUG, log_id_flow, "Processing a flow CLEAR REQ mgmt message\n");
+
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ /*
+ * Find the specified flow instance
+ */
+ p_flow_inst = flow_inst_get(p_flow_key, FLOW_FLAG_ACTIVE, NULL);
+
+ if(NULL == p_flow_inst)
+ {
+ /* This is a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_flow, "ERROR - Specified flow (%d:%s) not found\n",
+ p_flow_key->flow_id,
+ CORE_FSM_FLOW_TYPE_GET_STR(p_flow_key->flow_type));
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ } while(0);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
+
+ if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
+ {
+ /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
+ ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
+ break;
+ }
+
+ /* Merge the requested flow data with the current flow data,
+ * and this is the new request.
+ */
+ bcmbal_flow_object_overlay_w_dst_priority(&p_flow_inst->api_req_flow_info,
+ &p_flow_inst->current_flow_info);
+ /*
+ * Run the flow FSM to process this event
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ fsm_event.event_type = FLOW_FSM_EVENT_TYPE_REMOVE;
+
+ ret = flow_fsm_exec(p_flow_inst, &fsm_event);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_flow, "Unsupported operation on flow object (%d)\n",
+ oper_type );
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_flow);
+
+ break;
+ }
+ }
+
+ BCM_LOG(DEBUG, log_id_flow, "%s returns : %s\n", __FUNCTION__, bcmos_strerror(ret));
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to process a flow object event received
+ * from one of the BAL apps.
+ *
+ * @param msg_payload A pointer to the util message
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_flow_util_msg(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ flow_inst *p_flow_inst;
+ flow_fsm_event fsm_event;
+ bcmbal_msg_type type;
+ bcmbal_flow_key key;
+
+ type = bcmbal_type_minor_get(msg_payload);
+
+ BCM_LOG(DEBUG, log_id_flow, "processing a flow %s util message from %s\n",
+ bcmbal_msg_t_str[type],
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ /* recover the key from the message */
+ key = ((bal_util_msg_ind *)msg_payload)->obj_key.flow_key;
+
+ do
+ {
+ BCM_LOG(DEBUG, log_id_flow, "Got flow key id from util message (%d)\n", key.flow_id);
+
+ /*
+ * Get the flow instance that's being referenced
+ */
+ if(NULL == (p_flow_inst = flow_inst_get(&key, FLOW_FLAG_ACTIVE, NULL)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "invalid flow (%d, %s) found while processing a util message from %s\n",
+ key.flow_id,
+ CORE_FSM_FLOW_TYPE_GET_STR(key.flow_type),
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ ret = BCM_ERR_INTERNAL;
+
+ break;
+ }
+
+ /*
+ * Record the msg for further processing access
+ */
+ fsm_event.msg = msg_payload;
+
+ if (BAL_MSG_TYPE_IND == type)
+ {
+ fsm_event.event_type = FLOW_FSM_EVENT_TYPE_UTIL_MSG;
+ }
+ else if (BAL_MSG_TYPE_AUTO_IND == type)
+ {
+ fsm_event.event_type = FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG;
+ }
+ else
+ {
+ ret = BCM_ERR_NOT_SUPPORTED;
+ BCM_LOG(ERROR, log_id_flow,
+ "Unknown message type received from the UTIL"
+ " (not one of IND:AUTO_IND) (type:%d)\n",
+ type);
+ break;
+ }
+
+ /*
+ * Run the Flow FSM to process this event
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ ret = flow_fsm_exec(p_flow_inst, &fsm_event);
+ }
+ }
+ while(0);
+
+ return ret;
+}
+
+/*
+ * Helper functions
+ */
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a flow instance of the specified
+ * class.
+ *
+ * @param key A pointer to the key of the flow being
+ * referenced
+ * @param search_flag A flag specifying the type of flow
+ * instance to be retrieved
+ *
+ * @param is_new_flow A returned value signifying whether a found flow was on the free list
+ *
+ * @returns flow_inst_t* A pointer to the found flow instance,
+ * or NULL if one is not found
+ *
+ *****************************************************************************/
+static flow_inst *flow_inst_get(bcmbal_flow_key *key, flow_flag search_flag, bcmos_bool *is_new_flow)
+{
+ flow_inst *current_entry = NULL;
+
+ if(NULL != is_new_flow)
+ {
+ *is_new_flow = BCMOS_FALSE;
+ }
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ if(FLOW_FLAG_ACTIVE & search_flag)
+ {
+ TAILQ_FOREACH(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next)
+ {
+
+ if((current_entry->api_req_flow_info.key.flow_id == key->flow_id)
+ &&
+ ((FLOW_FLAG_IGNORE_DIR & search_flag) ?
+ 1:(current_entry->api_req_flow_info.key.flow_type == key->flow_type)))
+ {
+ BCM_LOG(DEBUG, log_id_flow, "Found active flow\n");
+ /* The flow instance pointer is in current_entry */
+ break;
+ }
+ }
+ }
+
+ /*
+ * Next, check the free list if the caller has chosen to do so
+ */
+ if((FLOW_FLAG_FREE & search_flag) && (NULL == current_entry))
+ {
+ /* Now check the free list */
+ if(!TAILQ_EMPTY(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list))
+ {
+ /* Just grab the first entry */
+ current_entry = TAILQ_FIRST(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list);
+
+ /* Remove it from the free list */
+ TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, current_entry, flow_inst_next);
+
+ /* And add it to the active list */
+ TAILQ_INSERT_TAIL(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
+
+ /*
+ * Initialize the fsm state and some of the fields
+ */
+ current_entry->fsm_state = FLOW_FSM_STATE_NULL;
+ current_entry->p_peer_flow_inst = NULL;
+
+ if(NULL != is_new_flow)
+ {
+ *is_new_flow = BCMOS_TRUE;
+ }
+
+ BCM_LOG(DEBUG, log_id_flow, "Using new flow\n");
+
+ }
+ }
+
+ if((FLOW_FLAG_ANY & search_flag) && (NULL == current_entry))
+ {
+ /*A flow was not found on either list */
+ BCM_LOG(DEBUG, log_id_flow, "************** ERROR: no flow found\n");
+ }
+
+ return current_entry;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a flow instance by access_if_id and svc_port_id
+ *
+ * @param access_if_id access interface id of the flow being searched
+ * @param type flow type (direction)
+ * @param svc_port_id svc_port_id of the flow being searched
+ *
+ * @returns flow_inst_t* A pointer to the found flow instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+flow_inst *flow_get_by_svc_id(uint16_t access_if_id, bcmbal_flow_type type, bcmbal_service_port_id svc_port_id)
+{
+ flow_inst *current_entry = NULL;
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ TAILQ_FOREACH(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next)
+ {
+
+ if((current_entry->api_req_flow_info.data.access_int_id == access_if_id)
+ &&
+ (current_entry->api_req_flow_info.key.flow_type == type)
+ &&
+ (current_entry->api_req_flow_info.data.svc_port_id == svc_port_id))
+ {
+ /* The flow instance pointer is in current_entry */
+ break;
+ }
+ }
+
+ return current_entry;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve the current flow info for the specified
+ * flow instance.
+ *
+ * @param key A flow key
+ *
+ * @returns bcmbal_flow_cfg* A pointer to the current flow info for the
+ * specified flow, or NULL if the flow is not found
+ *****************************************************************************/
+bcmbal_flow_cfg *flow_get_current_info_by_key(bcmbal_flow_key key)
+{
+ flow_inst *current_entry = NULL;
+
+ /*
+ * Check the active list
+ */
+ TAILQ_FOREACH(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next)
+ {
+
+ if((current_entry->current_flow_info.key.flow_id == key.flow_id)
+ &&
+ (current_entry->current_flow_info.key.flow_type == key.flow_type))
+ {
+ /* The flow instance pointer is in current_entry */
+ break;
+ }
+ }
+
+ if(current_entry)
+ {
+ return &(current_entry->current_flow_info);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a flow instance by access_if_id and agg_port_id
+ *
+ * @param access_if_id access interface id of the flow being searched
+ * @param agg_port_id svc_port_id of the flow being searched
+ *
+ * @returns flow_inst_t* A pointer to the found flow instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+flow_inst *flow_get_by_agg_id(uint16_t access_if_id, bcmbal_aggregation_port_id agg_port_id)
+{
+ flow_inst *current_entry = NULL;
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ TAILQ_FOREACH(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next)
+ {
+
+ if((current_entry->current_flow_info.data.access_int_id == access_if_id)
+ &&
+ (current_entry->current_flow_info.key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ &&
+ (current_entry->current_flow_info.data.agg_port_id == agg_port_id))
+ {
+ /* The flow instance pointer is in current_entry */
+ break;
+ }
+ }
+
+ return current_entry;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve the first flow instance associated with
+ * a subscriber terminal
+ *
+ * @param access_if_id access interface id of the flow being searched
+ * @param type flow type (direction)
+ * @param sub_term_id the subscriber terminal associated with the flow being
+ * searched
+ * @param sub_term_uni uni port on ONU
+ *
+ * @returns flow_inst_t* A pointer to the found flow instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+static flow_inst *flow_get_first_by_sub_term(uint16_t access_if_id,
+ bcmbal_flow_type type,
+ uint16_t sub_term_id,
+ uint16_t sub_term_uni)
+{
+ flow_inst *current_entry = NULL;
+ flow_inst *matched_entry = NULL;
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ TAILQ_FOREACH(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next)
+ {
+
+ if((current_entry->current_flow_info.data.access_int_id == access_if_id)
+ &&
+ (current_entry->current_flow_info.key.flow_type == type)
+ &&
+ (current_entry->current_flow_info.data.sub_term_id == sub_term_id)
+ &&
+ (current_entry->current_flow_info.data.sub_term_uni_idx == sub_term_uni))
+ {
+ /* The flow instance pointer is in current_entry */
+ matched_entry = current_entry;
+ break;
+ }
+ else if((current_entry->current_flow_info.data.access_int_id == access_if_id)
+ &&
+ (current_entry->current_flow_info.key.flow_type == type)
+ &&
+ (current_entry->current_flow_info.data.sub_term_id == sub_term_id))
+ {
+ if(NULL == matched_entry)
+ matched_entry = current_entry; /* store the first matched entry irrespective of uni port match */
+ }
+ }
+
+ return matched_entry;
+}
+
+
+bcmos_errno svc_port_id_for_sub_term_ds_flow_get(uint16_t access_if_id,
+ uint16_t sub_term_id,
+ uint16_t sub_term_uni,
+ uint16_t *svc_port_id)
+{
+ flow_inst *p_flow_inst;
+ bcmos_errno ret = BCM_ERR_OK;
+
+ if(NULL == (p_flow_inst = flow_get_first_by_sub_term(access_if_id,
+ BCMBAL_FLOW_TYPE_DOWNSTREAM,
+ sub_term_id,
+ sub_term_uni)))
+ {
+ ret = BCM_ERR_NOENT;
+ }
+ else
+ {
+ *svc_port_id = p_flow_inst->current_flow_info.data.svc_port_id;
+ }
+
+ return ret;
+
+}
+
+#ifdef FREE_FLOW_BY_KEY_SUPPORTED
+/*****************************************************************************/
+/**
+ * @brief A function to free a flow instance specified by a supplied key.
+ *
+ *
+ * @param key A pointer to the key of the subscriber terminal instance to be freed
+ *
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_free_by_key(bcmbal_flow_key *key)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ flow_inst *current_entry;
+ flow_inst *p_temp_entry;
+
+ BUG_ON(NULL == key);
+
+ /*
+ * First, check the active list (an active flow can be in the adding or removing state)
+ */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next,
+ p_temp_entry)
+ {
+ if((current_entry->api_req_flow_info.key.flow_id == key->flow_id) &&
+ (current_entry->api_req_flow_info.key.flow_type == key->flow_type))
+ {
+
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
+
+ /* And add it to the free list */
+ current_entry->fsm_state = FLOW_FSM_STATE_NULL;
+ current_entry->p_sub_term_fsm = NULL;
+ TAILQ_INSERT_TAIL(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, current_entry, flow_inst_next);
+ break;
+ }
+ }
+
+ return ret;
+}
+#endif
+
+/*****************************************************************************/
+/**
+ * @brief A function to free a flow instance specified by a the supplied
+ * entry pointer.
+ *
+ * @param p_entry A pointer to the entry to be freed
+ *
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno flow_free_by_entry(flow_inst *p_entry)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ flow_inst *current_entry;
+ flow_inst *p_temp_entry;
+
+ /*
+ * First, check the active list (an active flow can be in the adding or removing state)
+ */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list,
+ flow_inst_next,
+ p_temp_entry)
+ {
+ if(current_entry == p_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&FLOW_FSM_FLOW_LIST_CTX_PTR->active_flow_list, current_entry, flow_inst_next);
+ break;
+ }
+ }
+
+ /* And add it to the free list */
+ p_entry->fsm_state = FLOW_FSM_STATE_NULL;
+
+ /* And initialize the current object in the flow instance */
+ flow_inst_entry_obj_init(p_entry);
+
+ TAILQ_INSERT_TAIL(&FLOW_FSM_FLOW_LIST_CTX_PTR->free_flow_list, p_entry, flow_inst_next);
+
+ return ret;
+}
+
+static bcmos_errno flow_tm_auto_create(bcmbal_flow_cfg *p_flow_info, tm_sched_inst **p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_cfg tm_sched_default_cfg;
+ bcmbal_tm_sched_owner owner;
+ bcmbal_tm_sched_key tm_sched_key;
+ do
+ {
+ tm_sched_key.dir = BCMBAL_TM_SCHED_DIR_US;
+ BCMBAL_CFG_INIT(&tm_sched_default_cfg, tm_sched, tm_sched_key);
+ owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
+ owner.u.agg_port.intf_id = p_flow_info->data.access_int_id;
+ owner.u.agg_port.sub_term_id = p_flow_info->data.sub_term_id;
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, owner, owner);
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_AUTO);
+ if(BCMBAL_CFG_PROP_IS_SET(p_flow_info,flow,sla))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&(tm_sched_default_cfg.data.rate),tm_shaping, sbr, p_flow_info->data.sla.min_rate);
+ BCMBAL_ATTRIBUTE_PROP_SET(&(tm_sched_default_cfg.data.rate),tm_shaping, pbr, p_flow_info->data.sla.max_rate);
+ }
+ if (BCM_ERR_OK != (ret = bcmbal_tm_sched_auto_create(tm_sched_default_cfg, p_tm_sched_inst)))
+ {
+ BCM_LOG(ERROR, log_id_flow, "Could not create the auto tm sched\n");
+ break;
+ }
+ }while(0);
+ return ret;
+}
+
+static bcmos_errno flow_tm_get(bcmbal_flow_cfg *p_flow_info, tm_sched_inst **p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow_info,
+ flow,
+ agg_port_id))
+ {
+ BCM_LOG(DEBUG, log_id_flow,
+ "Using ALLOC ID supplied by the user (%d)\n",
+ p_flow_info->data.agg_port_id );
+
+ *p_tm_sched_inst = tm_sched_find_agg_port_node(p_flow_info->data.access_int_id, p_flow_info->data.agg_port_id);
+ if(NULL == *p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "agg port %d (intf id %d sub term id %d ) has no tm sched\n",
+ p_flow_info->data.agg_port_id, p_flow_info->data.access_int_id, p_flow_info->data.sub_term_id);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(p_flow_info->data.sub_term_id != (*p_tm_sched_inst)->req_tm_sched_info.data.owner.u.agg_port.sub_term_id)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "agg port %d (intf id %d) is already assign to sub term %d (not %d) \n",
+ p_flow_info->data.agg_port_id, p_flow_info->data.access_int_id,
+ (*p_tm_sched_inst)->req_tm_sched_info.data.owner.u.agg_port.sub_term_id,
+ p_flow_info->data.sub_term_id);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_flow, "Getting a new ALLOC ID from resource manager\n");
+ /*create a new agg port tm and allocate a new agg port id */
+ ret = flow_tm_auto_create(p_flow_info, p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_flow,
+ "could not create the auto tm sched for agg port %d (intf id %d)\n",
+ p_flow_info->data.agg_port_id, p_flow_info->data.access_int_id);
+ break;
+ }
+ BCMBAL_CFG_PROP_SET(p_flow_info, flow, agg_port_id,
+ (*p_tm_sched_inst)->req_tm_sched_info.data.owner.u.agg_port.agg_port_id);
+ }
+ }while(0);
+ return ret;
+}
+/*@}*/
diff --git a/bal_release/src/core/main/flow_fsm.h b/bal_release/src/core/main/flow_fsm.h
new file mode 100755
index 0000000..c6bb3a0
--- /dev/null
+++ b/bal_release/src/core/main/flow_fsm.h
@@ -0,0 +1,170 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file flow_fsm.h
+ * @brief Code to support the BAL Flow FSM
+ *
+ * @defgroup flow Flow
+ * @ingroup core
+ */
+
+#ifndef FLOW_FSM_H
+#define FLOW_FSM_H
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bal_api.h>
+
+#define FLOW_ALLOCATION_BLOCK_SIZE (16384)
+
+#define CORE_FSM_FLOW_TYPE_GET_STR(_fsm_flow_type) (BCMBAL_FLOW_TYPE_MULTICAST == (_fsm_flow_type) ? "Multicast":\
+ BCMBAL_FLOW_TYPE_BROADCAST == (_fsm_flow_type) ? "Broadcast":\
+ BCMBAL_FLOW_TYPE_DOWNSTREAM == (_fsm_flow_type) ? "Downstream":\
+ BCMBAL_FLOW_TYPE_UPSTREAM == (_fsm_flow_type) ? "Upstream":"Invalid")
+
+
+typedef enum
+{
+ FLOW_FSM_EVENT_TYPE_NONE = -1,
+ FLOW_FSM_EVENT_TYPE_ADMIN_UP ,
+ FLOW_FSM_EVENT_TYPE_ADMIN_DN ,
+ FLOW_FSM_EVENT_TYPE_REMOVE ,
+ FLOW_FSM_EVENT_TYPE_UTIL_MSG ,
+ FLOW_FSM_EVENT_TYPE_UTIL_AUTO_MSG ,
+
+
+ FLOW_FSM_EVENT_TYPE__LAST,
+ FLOW_FSM_EVENT_TYPE__NUM_OF
+} flow_fsm_event_type;
+
+
+
+typedef enum
+{
+ FLOW_FSM_STATE_NONE = -1,
+ FLOW_FSM_STATE_NULL ,
+ FLOW_FSM_STATE_CONFIGURING ,
+ FLOW_FSM_STATE_CONFIGURED ,
+ FLOW_FSM_STATE_REMOVING ,
+
+
+ FLOW_FSM_STATE__LAST,
+ FLOW_FSM_STATE__NUM_OF
+} flow_fsm_state;
+
+
+typedef enum
+{
+ FLOW_FLAG_ACTIVE = 1<<0, /**< A flow is on the active list */
+ FLOW_FLAG_FREE = 1<<1, /**< A flow is on the free list */
+ FLOW_FLAG_ANY = (FLOW_FLAG_ACTIVE | FLOW_FLAG_FREE), /**< A flow is on either the active or free list */
+ FLOW_FLAG_IGNORE_DIR = 1<<2 /**< Ignore direction during operation */
+} flow_flag;
+
+
+typedef struct flow_fsm_event_t
+{
+ flow_fsm_event_type event_type; /**< The flow fsm events */
+ void *msg;
+
+ /* other necessary information */
+} flow_fsm_event;
+
+
+/* Flow state in MAC plugin */
+typedef enum
+{
+ FLOW_MAC_STATE_NONE = 0x00, /**< Neither svc_id nor agg_id configured */
+ FLOW_MAC_STATE_SVC = 1<<0, /**< SVC is configured */
+ FLOW_MAC_STATE_AGG = 1<<1, /**< AGG is configured */
+ FLOW_MAC_STATE_READY = (FLOW_MAC_STATE_SVC | FLOW_MAC_STATE_AGG)
+} flow_mac_state;
+
+typedef struct flow_inst flow_inst;
+struct flow_inst
+{
+ bcmbal_flow_cfg current_flow_info; /**< The current information for this flow (used for GET) */
+ bcmbal_flow_cfg api_req_flow_info; /**< The last flow object info received from the Public API */
+ flow_fsm_state fsm_state; /**< The Flow FSM state */
+ flow_mac_state mac_state; /**< Flow state from MAC point of view */
+ struct flow_inst *p_peer_flow_inst; /**< Pointer to the linked flow in the opposite direction (if any) */
+ struct sub_term_inst *p_sub_term_inst; /**< Pointer to subscriber terminal instance associated with this flow */
+ bcmos_timer timer_info; /**< A structure used for the state machine timeout timer */
+ TAILQ_ENTRY(flow_inst) flow_inst_next ; /**< TAILQ link */
+ TAILQ_ENTRY(flow_inst) rsc_mgr_list_next ; /**< TAILQ link used for storing in Resource mgr list */
+};
+
+
+/*
+ * Flow FSM data structures
+ */
+typedef struct flow_fsm_ctx
+{
+ /* Lists of free flow entries and active flow entries
+ */
+ TAILQ_HEAD(free_flow_list_head, flow_inst) free_flow_list;
+
+ TAILQ_HEAD(active_flow_list_head, flow_inst) active_flow_list;
+
+} flow_fsm_ctx;
+
+
+/*
+ * Function declarations
+ */
+extern bcmos_errno flow_fsm_init(void);
+extern bcmos_errno flow_fsm_finish(void);
+
+extern bcmos_errno process_flow_object(void *msg_payload);
+
+extern bcmos_errno process_flow_util_msg(void *msg_payload);
+
+extern flow_inst *flow_get_by_svc_id(uint16_t access_if_id,
+ bcmbal_flow_type type,
+ bcmbal_service_port_id svc_port_id);
+
+extern flow_inst *flow_get_by_agg_id(uint16_t access_if_id,
+ bcmbal_aggregation_port_id agg_port_id);
+
+extern bcmos_errno svc_port_id_for_sub_term_ds_flow_get(uint16_t access_if_id,
+ uint16_t sub_term_id,
+ uint16_t sub_term_uni,
+ uint16_t *svc_port_id);
+
+extern bcmbal_flow_cfg *flow_get_current_info_by_key(bcmbal_flow_key key);
+
+
+/*@}*/
+
+#endif /*FLOW_FSM_H */
+
diff --git a/bal_release/src/core/main/fsm_common.c b/bal_release/src/core/main/fsm_common.c
new file mode 100644
index 0000000..0e1a8e5
--- /dev/null
+++ b/bal_release/src/core/main/fsm_common.c
@@ -0,0 +1,358 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file fsm_common.c
+ * @brief Common code to support the BAL access terminal FSMs
+ *
+ * @addtogroup core
+ */
+
+/*@{*/
+
+/*--- project includes ---*/
+#include <bcmos_system.h>
+#include <acc_term_fsm.h>
+#include <bal_msg.h>
+#include <bal_api.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include <bal_osmsg.h>
+#include <fsm_common.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+#endif
+
+
+/*****************************************************************************/
+/**
+ * @brief Send a management message response
+ *
+ * A Worker module function that sends the specified message to the
+ * BAL Public API.
+ *
+ * @param cmd_status The results of the command associated with the message
+ *
+ * @param msg_payload A pointer to the message to be sent
+ *
+ * @param oper_type The operation type of the object in this response
+ *
+ * @param log_id The log id of the calling component
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+bcmos_errno mgmt_msg_send_balapi_rsp(bcmos_errno cmd_status,
+ void *msg_payload,
+ bcmbal_obj_msg_type oper_type,
+ dev_log_id log_id)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Parameter checks */
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id, "sending rsp message to the public api (payload at %p)\n",
+ msg_payload);
+
+ /*
+ * Send the response back to the BAL Public API backend
+ */
+ bcmbal_msg_hdr_set(msg_payload,
+ bcmbal_type_major_get(msg_payload),
+ BAL_MSG_TYPE_RSP,
+ BAL_SUBSYSTEM_CORE,
+ bcmbal_msg_id_obj_get(msg_payload),
+ bcmbal_msg_id_oper_get(msg_payload),
+ bcmbal_ex_id_get(msg_payload));
+
+ /* Return the command status to the Public API backend */
+ ((bcmbal_obj *)(msg_payload))->status = cmd_status;
+
+ ((bcmbal_obj *)(msg_payload))->dir = BCMBAL_OBJ_MSG_DIR_RESPONSE;
+
+ ((bcmbal_obj *)(msg_payload))->type = oper_type;
+
+ if(BCM_ERR_OK != cmd_status)
+ {
+ ((bcmbal_obj *)(msg_payload))->presence_mask = 0;
+ }
+
+ /* Send message, but don't free it. It is still being used by FSM */
+ if(BCM_ERR_OK != (ret = bcmbal_msg_send(p_bal_core_to_api_queue, msg_payload, BCMOS_MSG_SEND_NO_FREE_ON_ERROR)))
+ {
+ BCM_LOG(ERROR, log_id, "msg_send failed to send rsp to core (error:%s)\n",
+ bcmos_strerror(ret));
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id, "RSP message sent to the public api with status=%s\n",
+ bcmos_strerror(cmd_status));
+ }
+
+ return ret;
+
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief Send a management message indication
+ *
+ * A Worker module function that sends the specified message to the
+ * BAL Public API.
+ *
+ * @param cmd_status The results of the command associated with the message
+ *
+ * @param is_auto_ind Set to BCMOS_TRUE if the indication to be sent is an AUTO IND
+ *
+ * @param msg_payload A pointer to the message to be sent (a BAL object!) (may be NULL)
+ *
+ * @param log_id The log id of the calling component
+ *
+ * @returns bcmos_errno
+ *
+ *****************************************************************************/
+static bcmos_errno _mgmt_msg_send_balapi_ind(bcmos_errno cmd_status,
+ bcmos_bool is_auto_ind,
+ void *msg_payload, /* If this is NULL, there is no message body */
+ dev_log_id log_id)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ uint16_t payload_size;
+ void *p_ind_msg;
+ bcmbal_obj_id obj_type;
+
+ if(NULL == msg_payload)
+ {
+ obj_type = BCMBAL_OBJ_ID_ANY;
+ payload_size = sizeof(bcmbal_obj);
+ }
+ else
+ {
+ switch(((bcmbal_obj *)msg_payload)->obj_type)
+ {
+ case (BCMBAL_OBJ_ID_FLOW):
+ {
+ payload_size = sizeof(bcmbal_flow_cfg);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_ACCESS_TERMINAL):
+ {
+ payload_size = sizeof(bcmbal_access_terminal_cfg);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_INTERFACE):
+ {
+ payload_size = sizeof(bcmbal_interface_cfg);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL):
+ {
+ payload_size = sizeof(bcmbal_subscriber_terminal_cfg);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_GROUP):
+ {
+ payload_size = sizeof(bcmbal_group_cfg);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_TM_SCHED):
+ {
+ payload_size = sizeof(bcmbal_tm_sched_cfg);
+ break;
+ }
+
+ case (BCMBAL_OBJ_ID_TM_QUEUE):
+ {
+ payload_size = sizeof(bcmbal_tm_queue_cfg);
+ break;
+ }
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id, "indication for object (%d) not supported\n",
+ ((bcmbal_obj *)msg_payload)->obj_type);
+ ret = BCM_ERR_PARM;
+ goto out;
+ }
+ }
+
+ }
+
+ p_ind_msg = bcmbal_msg_calloc(payload_size);
+
+ if(NULL == msg_payload)
+ {
+ ((bcmbal_obj *)p_ind_msg)->obj_type = obj_type;
+ }
+ else
+ {
+ memcpy(p_ind_msg, msg_payload, payload_size);
+ }
+
+ /*
+ * Send the indication back to the BAL Public API backend
+ */
+ bcmbal_msg_hdr_set(p_ind_msg,
+ BCMBAL_MGMT_API_IND_MSG,
+ (BCMOS_TRUE == is_auto_ind) ? BAL_MSG_TYPE_AUTO_IND : BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_CORE,
+ ((bcmbal_obj *)p_ind_msg)->obj_type,
+ 0,
+ 0);
+
+ /* Return the command status to the Public API backend */
+ ((bcmbal_obj *)(p_ind_msg))->status = cmd_status;
+
+ ((bcmbal_obj *)(p_ind_msg))->type = BCMBAL_OBJ_MSG_TYPE_GET;
+ ((bcmbal_obj *)(p_ind_msg))->dir = BCMBAL_OBJ_MSG_DIR_RESPONSE;
+
+ BCM_LOG(DEBUG, log_id, "sending IND message to the public api (payload at %p)\n", p_ind_msg);
+
+ if(BCM_ERR_OK != (ret = bcmbal_msg_send(p_bal_core_to_api_ind_queue, p_ind_msg, BCMOS_MSG_SEND_AUTO_FREE)))
+ {
+ BCM_LOG(ERROR, log_id, "msg_send failed to send IND to public API (%s)\n", bcmos_strerror(ret));
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id, "IND message sent to the public api with status=%s\n",
+ bcmos_strerror(cmd_status));
+ }
+
+ out:
+ return ret;
+
+}
+
+bcmos_errno mgmt_msg_send_balapi_ind(bcmos_errno cmd_status,
+ void *msg_payload, /* If this is NULL, there is no message body */
+ dev_log_id log_id)
+{
+
+ return _mgmt_msg_send_balapi_ind(cmd_status,
+ BCMOS_FALSE,
+ msg_payload,
+ log_id);
+}
+
+bcmos_errno mgmt_msg_send_balapi_auto_ind(bcmos_errno cmd_status,
+ void *msg_payload, /* If this is NULL, there is no message body */
+ dev_log_id log_id)
+{
+
+ return _mgmt_msg_send_balapi_ind(cmd_status,
+ BCMOS_TRUE,
+ msg_payload,
+ log_id);
+}
+
+/*****************************************************************************/
+/**
+ * @brief Create and Start the FSM timer
+ *
+ * @param p_timer_inst A pointer to an instance of a timer data structure
+ *
+ * @param p_inst An opaque pointer to an FSM instance to be passed to the timer
+ * expiry handler
+ *
+ * @param p_timer_expiry_handler A timer expiry handler function
+ *
+ * @param delay The delay interval (in mS) for this timer to run before the
+ * expiry handler is called
+ *
+ * @param log_id The log_id to use when logging errors encountered in this
+ * function
+ *
+ * @returns bcmos_errno
+ */
+bcmos_errno fsm_timer_start(bcmos_timer *p_timer_inst,
+ void *p_inst,
+ F_bcmos_timer_handler p_timer_expiry_handler,
+ uint32_t delay, /* delay is in mS */
+ dev_log_id log_id)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmos_timer_parm timer_spec;
+
+ /* Parameter checks */
+ BUG_ON(p_inst == NULL);
+ BUG_ON(p_timer_expiry_handler == NULL);
+ BUG_ON(p_timer_inst == NULL);
+
+
+ /* Create bcm_os timer */
+ timer_spec.owner = BCMOS_MODULE_ID_WORKER_MGMT;
+ timer_spec.handler = p_timer_expiry_handler;
+ timer_spec.data = (long) p_inst;
+ timer_spec.periodic = BCMOS_FALSE;
+
+ if (BCM_ERR_OK != bcmos_timer_create(p_timer_inst, &timer_spec))
+ {
+ BCM_LOG(ERROR, log_id, "Can't create timer for FSM\n");
+ ret = BCM_ERR_NORES;
+ }
+ else
+ {
+ /* Start the timer. Timer resolution is in uS*/
+ bcmos_timer_start(p_timer_inst, delay*1000);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief Stop and delete the specified FSM timer
+ *
+ * @param p_timer_inst A pointer to an instance of a timer data structure
+ *
+ */
+void fsm_timer_stop(bcmos_timer *p_timer_inst)
+{
+ /* Parameter checks */
+ BUG_ON(p_timer_inst == NULL);
+
+ bcmos_timer_destroy(p_timer_inst);
+}
+
+/*@}*/
diff --git a/bal_release/src/core/main/fsm_common.h b/bal_release/src/core/main/fsm_common.h
new file mode 100644
index 0000000..0e5b803
--- /dev/null
+++ b/bal_release/src/core/main/fsm_common.h
@@ -0,0 +1,73 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file fsm_common.h
+ * @brief Common code to support the BAL Access Terminal FSMs
+ *
+ * @ingroup core
+ */
+#ifndef FSM_COMMON_H
+#define FSM_COMMON_H
+
+/*@{*/
+
+#include <bal_common.h>
+#include <bal_obj.h>
+
+#define TIMER_DURATION_1_SEC (1000)
+#define TIMER_DURATION_IN_SEC(time_in_seconds) (TIMER_DURATION_1_SEC*time_in_seconds)
+
+
+extern bcmos_errno mgmt_msg_send_balapi_rsp(bcmos_errno cmd_status,
+ void *msg_payload,
+ bcmbal_obj_msg_type oper_type,
+ dev_log_id log_id);
+
+extern bcmos_errno mgmt_msg_send_balapi_ind(bcmos_errno cmd_status,
+ void *msg_payload, /* If this is NULL, there is no message body */
+ dev_log_id log_id);
+
+extern bcmos_errno mgmt_msg_send_balapi_auto_ind(bcmos_errno cmd_status,
+ void *msg_payload, /* If this is NULL, there is no message body */
+ dev_log_id log_id);
+
+extern bcmos_errno fsm_timer_start(bcmos_timer *p_timer_inst,
+ void *p_inst,
+ F_bcmos_timer_handler p_timer_expiry_handler,
+ uint32_t delay, /* delay is in mS */
+ dev_log_id log_id);
+
+extern void fsm_timer_stop(bcmos_timer *p_timer_inst);
+
+/*@}*/
+
+#endif /*FSM_COMMON_H */
diff --git a/bal_release/src/core/main/group_fsm.c b/bal_release/src/core/main/group_fsm.c
new file mode 100644
index 0000000..97b0a45
--- /dev/null
+++ b/bal_release/src/core/main/group_fsm.c
@@ -0,0 +1,2162 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file group_fsm.c
+ * @brief Code to support the BAL group FSM
+ *
+ *
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <group_fsm.h>
+#include <bal_msg.h>
+#include <bal_osmsg.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include "rsc_mgr.h"
+
+#include <bal_objs.h>
+#include <fsm_common.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+ /*
+ * @brief The logging device id for group
+ */
+static dev_log_id log_id_group;
+#endif
+
+/* local function declarations */
+static bcmos_errno group_fsm_create(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_destroy(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_add(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_remove(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_set(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_configuring_util_msg(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_deleting_util_msg(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_ignore_api_msg(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_state_err(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event);
+
+static bcmos_errno group_fsm_exec(group_inst *p_group_inst, group_fsm_event *p_event);
+
+static group_inst *group_inst_get(bcmbal_group_key *key, group_flag search_flag);
+
+static bcmos_errno group_free_by_entry(group_inst *p_entry);
+
+static bcmos_errno bcmbal_group_object_member_remove(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group);
+
+static bcmos_errno bcmbal_group_object_member_add(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group);
+
+static bcmos_errno bcmbal_group_object_member_replace(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group);
+
+static bcmos_errno bcmbal_group_object_overlay(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group);
+ /*
+ * @brief The Global group fsm context data structure
+ */
+static group_fsm_ctx g_group_fsm_group_list_ctx;
+
+/*
+ * Macros for group ctx access
+ */
+#define GROUP_FSM_GROUP_LIST_CTX (g_group_fsm_group_list_ctx)
+#define GROUP_FSM_GROUP_LIST_CTX_PTR (&g_group_fsm_group_list_ctx)
+
+/*
+ * @brief The definition of a group FSM state processing function
+ */
+typedef bcmos_errno (* group_fsm_state_processor)(group_inst *, void *, group_fsm_event *);
+
+/*
+ * @brief The Group FSM state processing array
+ */
+static group_fsm_state_processor group_states[GROUP_FSM_STATE__NUM_OF][GROUP_FSM_EVENT_TYPE__NUM_OF] =
+{
+
+ [GROUP_FSM_STATE_NULL] =
+ {
+ /*
+ * Next state: COMFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_create,
+
+ /*
+ * Next state: NULL
+ */
+ [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_add,
+
+ /*
+ * Next state: NULL
+ */
+ [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_set,
+
+ },
+ [GROUP_FSM_STATE_CONFIGURING] =
+ {
+ /*
+ * Next state: COMFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: COMFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: CONFIGURED
+ */
+ [GROUP_FSM_EVENT_TYPE_UTIL_MSG] = group_fsm_configuring_util_msg,
+
+ },
+
+ [GROUP_FSM_STATE_CONFIGURED] =
+ {
+ /*
+ * Next state: COMFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: DELETING
+ */
+ [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_destroy,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_add,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_remove,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_set,
+
+ },
+
+ [GROUP_FSM_STATE_DELETING] =
+ {
+ /*
+ * Next state: DELETING
+ */
+ [GROUP_FSM_EVENT_TYPE_CREATE] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: DELETING
+ */
+ [GROUP_FSM_EVENT_TYPE_DESTROY] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: DELETING
+ */
+ [GROUP_FSM_EVENT_TYPE_ADD] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: DELETING
+ */
+ [GROUP_FSM_EVENT_TYPE_REMOVE] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: DELETING
+ */
+ [GROUP_FSM_EVENT_TYPE_SET] = group_fsm_ignore_api_msg,
+
+ /*
+ * Next state: NULL
+ */
+ [GROUP_FSM_EVENT_TYPE_UTIL_MSG] = group_fsm_deleting_util_msg,
+
+ },
+
+};
+
+static char *state_name_str[] =
+{
+ "GROUP_FSM_STATE_NULL",
+ "GROUP_FSM_STATE_CONFIGURING",
+ "GROUP_FSM_STATE_CONFIGURED",
+ "GROUP_FSM_STATE_DELETING",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (GROUP_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), group_fsm_state);
+
+static char *group_state_name_get(group_fsm_state state)
+{
+ if(state < GROUP_FSM_STATE__LAST)
+ {
+ return state_name_str[state];
+ }
+ else
+ {
+ return "GROUP_UNKNOWN";
+ }
+}
+
+static char *event_name_str[] =
+{
+ "GROUP_FSM_CREATE_EVENT",
+ "GROUP_FSM_DESTROY_EVENT",
+ "GROUP_FSM_ADD_EVENT",
+ "GROUP_FSM_REMOVE_EVENT",
+ "GROUP_FSM_SET_EVENT",
+ "GROUP_FSM_UTIL_MSG_EVENT",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (GROUP_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), group_fsm_event_type);
+
+static char *group_event_name_get(group_fsm_event_type event)
+{
+ if(event < GROUP_FSM_EVENT_TYPE__LAST)
+ {
+ return event_name_str[event];
+ }
+ else
+ {
+ return "GROUP_EVT_UNKNOWN";
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the current_group_info object of the
+ * supplied entry.
+ *
+ * @param p_entry A pointer to the entry to be initialized
+ *
+ *
+ * @returns void
+ *****************************************************************************/
+static void group_inst_entry_obj_init(group_inst *p_entry)
+{
+ /* The actual key content is irrelevant for free groups */
+ bcmbal_group_key key = { .group_id = 0 };
+
+ BCMBAL_CFG_INIT(&p_entry->current_group_info,
+ group,
+ key);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_group_info), BCMOS_FALSE);
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the Group FSM infrastructure.
+ *
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno group_fsm_init(void)
+{
+ int ii;
+ group_inst *new_entry;
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifdef ENABLE_LOG
+ log_id_group = bcm_dev_log_id_register("GROUP", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_group == DEV_LOG_INVALID_ID);
+#endif
+
+ /* Initialize all of the group queues */
+ TAILQ_INIT(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list);
+ TAILQ_INIT(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list);
+
+ /* Populate the free list with it's initial set of groups
+ */
+ for(ii=0; ii<GROUP_ALLOCATION_BLOCK_SIZE; ii++)
+ {
+
+ new_entry = bcmos_calloc(sizeof(group_inst));
+
+ if (NULL == new_entry)
+ {
+ BCM_LOG(FATAL, log_id_group, "Failed to initialize the group free list - FATAL\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ group_free_by_entry(new_entry);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to un-initialize the Group FSM infrastructure.
+ *
+ * NOTE: This is called once on shutdown and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno group_fsm_finish(void)
+{
+
+ group_inst *current_entry, *p_temp_entry;
+
+ /* Free all the entries on the active list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
+ group_inst_next,
+ p_temp_entry)
+ {
+ /* free up the internal allocated member info */
+ if(current_entry->current_group_info.data.members.val)
+ {
+ bcmos_free(current_entry->current_group_info.data.members.val);
+ }
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list, current_entry, group_inst_next);
+
+ bcmos_free(current_entry);
+
+ }
+
+ /* Free all the entries on the free list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list,
+ group_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list, current_entry, group_inst_next);
+
+ bcmos_free(current_entry);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing executive function
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_exec(group_inst *p_group_inst, group_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ group_fsm_state pre_state;
+ group_fsm_state_processor group_state_processor;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_group_inst);
+ BUG_ON(NULL == p_event);
+
+ /* Record the present state for debug printing
+ */
+ pre_state = p_group_inst->fsm_state;
+
+ /*
+ * Get the state processing function
+ */
+ group_state_processor = group_states[p_group_inst->fsm_state][p_event->event_type];
+
+ /*
+ * If there's a state processing function for this event and state, execute it.
+ * Otherwise, process a generic error.
+ */
+ if (group_state_processor)
+ {
+ ret = group_state_processor(p_group_inst, p_event->msg, p_event);
+ } else
+ {
+ group_fsm_state_err(p_group_inst, p_event->msg, p_event);
+ }
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_group, "*** Error detected during state processing\n");
+ p_group_inst->fsm_state = pre_state;
+ }
+
+ BCM_LOG(DEBUG, log_id_group, "*** Event %s, State: %s --> %s\n\n",
+ group_event_name_get(p_event->event_type),
+ group_state_name_get(pre_state),
+ group_state_name_get(p_group_inst->fsm_state));
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing for a group create command received
+ * from the BAL Public API.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_create(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ group_fsm_state pre_fsm_state;
+
+ BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - create group \n");
+
+ do
+ {
+ /* save the current state */
+ pre_fsm_state = p_group_inst->fsm_state;
+ /* change Group state to CONFIGURING */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Switch Utils to add applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_CREATE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while create group\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*– Core calls Mac Utils create applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_CREATE, BCMOS_TRUE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
+
+ /* Reverse the (just create) group in the switch, otherwise the switch utils
+ * will be out of sync with Core and Mac. There's not
+ * much we can do about it if reversing this group fails.
+ */
+ if(BCM_ERR_OK != sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_DESTROY))
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "error detected by switch util while reversing create group\n");
+ }
+ else
+ {
+ /* restore the original state */
+ p_group_inst->fsm_state = pre_fsm_state;
+ }
+
+ break;
+ }
+
+ /* The hardware has properly accepted the object info, so copy object to
+ * the current state.
+ */
+ bcmbal_group_object_overlay(&p_group_inst->api_req_group_info,
+ &p_group_inst->current_group_info);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_group);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing for a group destroy command received
+ * from the BAL Public API.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_destroy(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ group_fsm_state sav_state = p_group_inst->fsm_state;
+ bcmbal_group_cfg *p_group_cfg;
+ int i;
+
+ BCM_LOG(INFO, log_id_group, "Got CLEAR request from BAL API - destroy group \n");
+
+ do
+ {
+ /* change Group state to CONFIGURING */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_DELETING;
+
+ /* Destroy operation is best effort, as it is unlikely to fail */
+ /*– Core calls Switch Utils to add applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_DESTROY)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while destroy group\n", bcmos_strerror(ret));
+ /* if the group is busy, some flow still reference this group, skip the MAC and return error
+ no member has been clean up */
+ if(ret == BCM_ERR_INVALID_OP)
+ {
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
+ p_group_inst->fsm_state = sav_state;
+ mgmt_msg_send_balapi_ind(ret, msg, log_id_group);
+ return ret;
+ }
+ break;
+ }
+
+ /*– Core calls Mac Utils create applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_DESTROY, BCMOS_TRUE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /* The hardware has properly accepted the object info, so copy object to
+ * the current state.
+ */
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_group);
+ /* TBD, need logic to perform error recovery if SwitchUtil success and MacUtil failed */
+ }
+ else
+ {
+ /* update resource manager on svc_port_id usage - keep going as the Mac and Switch already clean up */
+ p_group_cfg = &p_group_inst->current_group_info;
+ for(i=0; i<p_group_cfg->data.members.len; i++)
+ {
+ if(BCM_ERR_OK != rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
+ p_group_cfg->data.members.val[i].svc_port_id,
+ NULL) )
+ {
+ BCM_LOG(ERROR, log_id_group,
+ " error encountered during destroy of group resources (gem_id: %d, intf_id:%d\n",
+ p_group_cfg->data.members.val[i].svc_port_id,
+ p_group_cfg->data.members.val[i].intf_id);
+ }
+ }
+ }
+
+ return ret;
+
+}
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing for a group set command received
+ * from the BAL Public API.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_set(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ group_inst group_inst_rvt;
+ bcmbal_group_cfg *p_group_cfg;
+ int i;
+
+ BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - replace group members\n");
+
+ do
+ {
+ /* save the current state */
+ group_inst_rvt.fsm_state = p_group_inst->fsm_state;
+ /* change Group state to CONFIGURING */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Switch Utils to add applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_SET)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while set group members\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*– Core calls Mac Utils add applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_SET, BCMOS_TRUE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
+
+ group_inst_rvt.current_group_info = p_group_inst->api_req_group_info;
+ group_inst_rvt.api_req_group_info = p_group_inst->current_group_info;
+ /* Reverse the (just set) group from the switch otherwise the switch utils
+ * will be out of sync with Core and Mac. There's not
+ * much we can do about it if reversing this group fails.
+ */
+ if(BCM_ERR_OK != sw_util_group_set(&group_inst_rvt, BAL_UTIL_OPER_GROUP_SET))
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "error detected by switch util while reversing group\n");
+ }
+ else
+ {
+ /* restore the original state */
+ p_group_inst->fsm_state = group_inst_rvt.fsm_state;
+ }
+
+ break;
+ }
+ /* update resource manager on svc_port_id usage - free the gem on old members */
+ p_group_cfg = &p_group_inst->current_group_info;
+ for(i=0; i<p_group_cfg->data.members.len; i++)
+ {
+ if(BCM_ERR_OK != rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
+ p_group_cfg->data.members.val[i].svc_port_id,
+ NULL) )
+ {
+ BCM_LOG(ERROR, log_id_group,
+ " error encountered during release of group resources (gem_id: %d, intf_id:%d\n",
+ p_group_cfg->data.members.val[i].svc_port_id,
+ p_group_cfg->data.members.val[i].intf_id);
+ }
+ }
+
+ /* set operation can be made without CREATE, so fill in the non-member info */
+ bcmbal_group_object_overlay(&p_group_inst->api_req_group_info,
+ &p_group_inst->current_group_info);
+
+ /* The hardware has properly accepted the object info, so the request object becomes
+ * the current state.
+ */
+ bcmbal_group_object_member_replace(&p_group_inst->api_req_group_info,
+ &p_group_inst->current_group_info);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_group);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing for a group add command received
+ * from the BAL Public API.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_add(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ group_fsm_state pre_fsm_state;
+
+ BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - add group members\n");
+
+ do
+ {
+ /* save the current state */
+ pre_fsm_state = p_group_inst->fsm_state;
+ /* change Group state to CONFIGURING */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Switch Utils to add applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_ADD)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while add group members\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*– Core calls Mac Utils add applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_ADD, BCMOS_TRUE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
+
+ /* Reverse the (just add) group member from the switch, otherwise the switch utils
+ * will be out of sync with Core and Mac. There's not
+ * much we can do about it if reversing this group fails.
+ */
+ if(BCM_ERR_OK != sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_REMOVE))
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "error detected by switch util while reversing add group\n");
+ }
+ else
+ {
+ /* restore the original state */
+ p_group_inst->fsm_state = pre_fsm_state;
+ }
+
+ break;
+ }
+
+ /* add operation can be made without CREATE, so fill in the non-member info */
+ bcmbal_group_object_overlay(&p_group_inst->api_req_group_info,
+ &p_group_inst->current_group_info);
+
+ /* The hardware has properly accepted the object info, so add object members to
+ * the current state.
+ */
+ bcmbal_group_object_member_add(&p_group_inst->api_req_group_info,
+ &p_group_inst->current_group_info);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_group);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing for a group remove command received
+ * from the BAL Public API.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_remove(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ group_fsm_state pre_fsm_state;
+ bcmbal_group_cfg *p_group_cfg;
+ int i;
+
+ BCM_LOG(INFO, log_id_group, "Got SET request from BAL API - remove group members\n");
+
+ do
+ {
+ /* save the current state */
+ pre_fsm_state = p_group_inst->fsm_state;
+ /* change Group state to CONFIGURING */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Switch Utils to add applicable CMDs */
+ if(BCM_ERR_OK != (ret = sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_REMOVE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by switch util while remove group members\n", bcmos_strerror(ret));
+ break;
+ }
+
+ /*– Core calls Mac Utils add applicable CMDs */
+ if(BCM_ERR_OK != (ret = mac_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_REMOVE, BCMOS_TRUE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "error %s detected by mac util\n", bcmos_strerror(ret));
+
+ /* Reverse the (just remove) group member from the switch, otherwise the switch utils
+ * will be out of sync with Core and Mac. There's not
+ * much we can do about it if reversing this group fails.
+ */
+ if(BCM_ERR_OK != sw_util_group_set(p_group_inst, BAL_UTIL_OPER_GROUP_ADD))
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "error detected by switch util while reversing remove group\n");
+ }
+ else
+ {
+ /* restore the original state */
+ p_group_inst->fsm_state = pre_fsm_state;
+ }
+
+ break;
+ }
+
+ /* update resource manager on svc_port_id usage */
+ p_group_cfg = &p_group_inst->api_req_group_info;
+ for(i=0; i<p_group_cfg->data.members.len; i++)
+ {
+ /* if interface is not a member (e.g. already removed), skip it */
+ if(p_group_cfg->data.members.val[i].svc_port_id == 0)
+ {
+ continue;
+ }
+ if(BCM_ERR_OK != rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
+ p_group_cfg->data.members.val[i].svc_port_id,
+ NULL) )
+ {
+ BCM_LOG(ERROR, log_id_group,
+ " error encountered during release of group resources (gem_id: %d, intf_id:%d\n",
+ p_group_cfg->data.members.val[i].svc_port_id,
+ p_group_cfg->data.members.val[i].intf_id);
+ }
+ }
+
+ /* The hardware has properly accepted the object info, so remove object members from
+ * the current state.
+ */
+ bcmbal_group_object_member_remove(&p_group_inst->api_req_group_info,
+ &p_group_inst->current_group_info);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_TRUE);
+
+ }while(0);
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_group);
+
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing function to ignore a received message.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_ignore_api_msg(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(WARNING, log_id_group, "Ignoring message from BAL API when in %s state \n", group_state_name_get(p_group_inst->fsm_state));
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing function to process a message from
+ * one of the BAL apps received when the specified group instance FSM
+ * is in the CONFIGURING state.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_configuring_util_msg(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_group_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ BCM_LOG(DEBUG, log_id_group,
+ " Received an IND message from BAL UTIL (%s) during CONFIGURING state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ BCM_LOG(DEBUG, log_id_group,
+ "%s, thread %s, module %d\n", __FUNCTION__, bcmos_task_current()->name, bcmos_module_current());
+
+ /* Handle indication */
+ ret = ind_msg->status;
+
+ /* Reflect the execution status in the object being returned in the indication
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ /*
+ * The group has been successfully configured
+ */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURED;
+
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_group, "Group %d: Failed in state %s. Error %s\n\n",
+ p_group_inst->api_req_group_info.key.group_id,
+ group_state_name_get(p_group_inst->fsm_state),
+ bcmos_strerror(ret));
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_FALSE);
+ p_group_inst->current_group_info.hdr.hdr.status = ret;
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_group_inst->current_group_info.hdr,
+ log_id_group);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM state processing function to process a
+ * message from one of the BAL apps received when the specified
+ * group instance FSM is in the DELETING state.
+ *
+ * @param p_group_inst Pointer to an group instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_deleting_util_msg(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_group_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ BCM_LOG(DEBUG, log_id_group,
+ " Received an IND message from BAL UTIL (%s) during DELETING state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+
+ /* Handle indication */
+ ret = ind_msg->status;
+
+ /* Reflect the execution status in the object being returned in the indication
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ p_group_inst->current_group_info.hdr.hdr.status = ret;
+
+ /*
+ * The group has been successfully destroy
+ */
+ p_group_inst->fsm_state = GROUP_FSM_STATE_NULL;
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_group_inst->current_group_info), BCMOS_FALSE);
+ /*
+ * Send the indication back to the BAL public API
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_group_inst->current_group_info.hdr,
+ log_id_group);
+
+ /* free up the member memory */
+ if( p_group_inst->current_group_info.data.members.val)
+ {
+ bcmos_free(p_group_inst->current_group_info.data.members.val);
+ p_group_inst->current_group_info.data.members.val = NULL;
+ p_group_inst->current_group_info.data.members.len = 0;
+ }
+
+ /* Return the group to the free pool */
+ group_free_by_entry(p_group_inst);
+
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_group, "Group %d: Failed in state %s. Error %s\n\n",
+ p_group_inst->current_group_info.key.group_id,
+ group_state_name_get(p_group_inst->fsm_state),
+ bcmos_strerror(ret));
+ p_group_inst->fsm_state = GROUP_FSM_STATE_CONFIGURED;
+
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Group FSM function which is executed when an error
+ * is encountered during FSM processing.
+ *
+ * @param p_group_inst Pointer to a group instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to a group event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_fsm_state_err(group_inst *p_group_inst,
+ void *msg,
+ group_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_INVALID_OP;
+
+ BCM_LOG(DEBUG, log_id_group,
+ "Error encountered processing GROUP FSM"
+ " - BAD EVENT ()\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function called by the core worker thread to process an
+ * group object message (SET, GET, CLEAR, STATS) received
+ * from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_group_object(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
+ bcmbal_group_cfg *p_group_cfg = (bcmbal_group_cfg *)msg_payload;
+ group_inst *p_group_inst = NULL;
+ group_fsm_event fsm_event;
+ bcmbal_group_key *p_group_key;
+ bcmbal_obj_msg_type oper_type;
+ int i, j, num_svc_port_allocated = 0;
+
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id_group, "Processing a group object\n");
+
+ p_group_key = &p_group_cfg->key;
+
+ oper_type = p_group_cfg->hdr.hdr.type;
+
+ /*
+ * A message pointer may be passed inside the event structure.
+ */
+ fsm_event.msg = msg_payload;
+
+ /* SET or GET or CLEAR...? */
+ switch (oper_type)
+ {
+ case (BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+ bcmos_bool b_generate_event = BCMOS_FALSE;
+
+ BCM_LOG(DEBUG, log_id_group,
+ "Processing a group SET REQ mgmt message\n");
+
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+ /*
+ * Find or create the specified group instance
+ */
+ p_group_inst = group_inst_get(p_group_key, GROUP_FLAG_ANY);
+ if(NULL == p_group_inst)
+ {
+ /* This is a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_group,
+ "ERROR - Group not found. No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ /* If the state of this group is in flux, then reject the SET request */
+ if(BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_group_inst->current_group_info)))
+ {
+ ret = BCM_ERR_IN_PROGRESS;
+ break;
+ }
+
+ /* if needed, request/validate svc_port_id from resource manager - before validation */
+ if (BCMBAL_CFG_PROP_IS_SET(p_group_cfg, group, members_cmd) )
+ {
+ if(p_group_cfg->data.members_cmd == BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS)
+ {
+ /* if service id is not specified, filled in with current config info */
+ for(i=0; i<p_group_cfg->data.members.len; i++)
+ {
+ int req_intf = p_group_cfg->data.members.val[i].intf_id;
+ if(p_group_cfg->data.members.val[i].svc_port_id == 0)
+ {
+ for(j=0; j<p_group_inst->current_group_info.data.members.len; j++)
+ {
+ int cur_intf = p_group_inst->current_group_info.data.members.val[j].intf_id;
+ if( cur_intf == req_intf)
+ {
+ p_group_cfg->data.members.val[i].svc_port_id = p_group_inst->current_group_info.data.members.val[j].svc_port_id;
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* if the group already has owner, alloc the svc_port for addition or replacement members */
+ if(BCMBAL_GROUP_OWNER_NONE != p_group_inst->current_group_info.data.owner )
+ {
+ /* copy the owner to the request */
+ BCMBAL_CFG_PROP_SET(p_group_cfg, group, owner, p_group_inst->current_group_info.data.owner);
+ /* allocate GEM */
+ for(i=0; i<p_group_cfg->data.members.len; i++)
+ {
+ if (BCMBAL_GROUP_OWNER_MULTICAST != p_group_inst->current_group_info.data.owner)
+ {
+ ret = rsc_mgr_gem_alloc_multicast(p_group_cfg->data.members.val[i].intf_id,
+ &p_group_cfg->data.members.val[i].svc_port_id,
+ 1, /* request gem range */
+ NULL);
+ }
+ else if (BCMBAL_GROUP_OWNER_UNICAST != p_group_inst->current_group_info.data.owner)
+ {
+ ret = rsc_mgr_gem_alloc_broadcast(p_group_cfg->data.members.val[i].intf_id,
+ &p_group_cfg->data.members.val[i].svc_port_id,
+ 1, /* request gem range */
+ NULL);
+ }
+ else
+ {
+ ret = BCM_ERR_PARM;
+ }
+ if(BCM_ERR_OK != ret)
+ {
+ break;
+ }
+ }
+ /* remember how many service port request been made to resource manager */
+ num_svc_port_allocated = i;
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_group,
+ " error encountered during allocate of group resources (intf_id:%d)\n",
+ p_group_cfg->data.members.val[i].intf_id);
+ break;
+ }
+ }
+
+ }
+ }
+
+ /*
+ * Fill in the local group info data structure
+ * Notice that any memory allocated in the request message will be free in
+ * process_mgmt_msg() of worker thread. If needed, GROUP FSM need to clone any
+ * request info into p_group_inst->current_group_info before return
+ */
+ p_group_inst->api_req_group_info = *p_group_cfg;
+
+ /*
+ * Process the request
+ */
+
+ /*
+ * Perform the validation check(s) that the utils require
+ */
+ if(BCM_ERR_OK != (ret = mac_util_group_info_validate(&p_group_inst->api_req_group_info)))
+ {
+ BCM_LOG(ERROR, log_id_group, "Failed GROUP mac validation\n");
+ break;
+ }
+
+ if(BCM_ERR_OK != (ret = sw_util_group_info_validate(&p_group_inst->api_req_group_info)))
+ {
+ BCM_LOG(ERROR, log_id_group, "Failed switch group validation\n");
+ break;
+ }
+
+ /* set the event based on request command */
+ b_generate_event = BCMOS_TRUE;
+ if ( BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_group_inst->api_req_group_info, group, members_cmd) )
+ {
+ switch(p_group_inst->api_req_group_info.data.members_cmd)
+ {
+ case BCMBAL_GROUP_MEMBER_CMD_ADD_MEMBERS:
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_ADD;
+ break;
+ case BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS:
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_REMOVE;
+ break;
+ case BCMBAL_GROUP_MEMBER_CMD_SET_MEMBERS:
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_SET;
+ break;
+ default:
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_NONE;
+ b_generate_event = BCMOS_FALSE;
+ break;
+ }
+ }
+ else
+ {
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_CREATE;
+ }
+
+ }while(0);
+
+ /* if anything go wrong, inform resource manager to free up the service port */
+ if (BCM_ERR_OK != ret &&
+ BCMBAL_CFG_PROP_IS_SET(p_group_cfg, group, members_cmd) &&
+ p_group_cfg->data.members_cmd != BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS)
+ {
+ for(i=0; i<num_svc_port_allocated; i++)
+ {
+ rsp_ret = rsc_mgr_gem_free(p_group_cfg->data.members.val[i].intf_id,
+ p_group_cfg->data.members.val[i].svc_port_id,
+ NULL);
+
+ /* best effort to free up */
+ if(BCM_ERR_OK != rsp_ret)
+ {
+ BCM_LOG(ERROR, log_id_group,
+ " error encountered during allocate of group resources (intf_id:%d)\n",
+ p_group_cfg->data.members.val[i].intf_id);
+ }
+ }
+ }
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
+
+ if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
+ {
+ /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
+ ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
+ break;
+ }
+
+ /* If there was an event generated, call the state machine exec */
+ if(BCMOS_TRUE == b_generate_event)
+ {
+ /*
+ * Run the group FSM to process this event
+ */
+ ret = group_fsm_exec(p_group_inst, &fsm_event);
+ }
+ break;
+ }
+
+ case (BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+
+ BCM_LOG(DEBUG, log_id_group, "Processing a group GET REQ mgmt message\n");
+
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ }
+ else
+ {
+ /*
+ * Find the specified group instance
+ */
+ p_group_inst = group_inst_get(p_group_key, GROUP_FLAG_ACTIVE);
+ }
+
+ if(NULL == p_group_inst)
+ {
+ if(BCM_ERR_STATE != ret)
+ {
+ /* This is not a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_group, "ERROR - Specified group (%d) not found\n",
+ p_group_key->group_id);
+
+ ret = BCM_ERR_NOENT;
+ }
+
+ break;
+ }
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ p_group_inst->current_group_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+ *((bcmbal_group_cfg *)msg_payload) = p_group_inst->current_group_info;
+
+ } while (0);
+
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
+
+ }
+ break;
+
+ case (BCMBAL_OBJ_MSG_TYPE_CLEAR):
+ {
+ BCM_LOG(DEBUG, log_id_group, "Processing a group CLEAR REQ mgmt message\n");
+
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ /*
+ * Find the specified group instance
+ */
+ p_group_inst = group_inst_get(p_group_key, GROUP_FLAG_ACTIVE);
+
+ if(NULL == p_group_inst)
+ {
+ /* This is a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_group, "ERROR - Specified group (%d: not found\n",
+ p_group_key->group_id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ } while(0);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
+
+ if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
+ {
+ /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */
+ ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret;
+ break;
+ }
+
+ /*
+ * Run the group FSM to process this event
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_DESTROY;
+
+ ret = group_fsm_exec(p_group_inst, &fsm_event);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_group, "Unsupported operation on group object (%d)\n",
+ oper_type );
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_group);
+
+ break;
+ }
+ }
+
+ BCM_LOG(DEBUG, log_id_group, "%s returns\n", __FUNCTION__);
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to process a group object event received
+ * from one of the BAL apps.
+ *
+ * @param msg_payload A pointer to the util message
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_group_util_msg(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ group_inst *p_group_inst;
+ group_fsm_event fsm_event;
+ bcmbal_msg_type type;
+ bcmbal_group_key key;
+
+ type = bcmbal_type_minor_get(msg_payload);
+
+ BCM_LOG(DEBUG, log_id_group, "processing a group %s util message from %s\n",
+ bcmbal_msg_t_str[type],
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ /* recover the key from the message */
+ key = ((bal_util_msg_ind *)msg_payload)->obj_key.group_key;
+
+ do
+ {
+ BCM_LOG(DEBUG, log_id_group, "Got group key id (%d) from util message\n", key.group_id);
+
+ /*
+ * Get the group instance that's being referenced
+ */
+ if(NULL == (p_group_inst = group_inst_get(&key, GROUP_FLAG_ACTIVE)))
+ {
+ BCM_LOG(ERROR, log_id_group, "invalid group (%d) found while processing a util message from %s\n",
+ key.group_id,
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ ret = BCM_ERR_INTERNAL;
+
+ break;
+ }
+
+ /*
+ * Record the msg for further processing access
+ */
+ fsm_event.msg = msg_payload;
+
+ if (BAL_MSG_TYPE_IND == type)
+ {
+ fsm_event.event_type = GROUP_FSM_EVENT_TYPE_UTIL_MSG;
+ }
+ else
+ {
+ ret = BCM_ERR_NOT_SUPPORTED;
+ BCM_LOG(ERROR, log_id_group,
+ "Unknown message type received from the UTIL"
+ " (not IND) (type:%d)\n",
+ type);
+ break;
+ }
+
+ /*
+ * Run the Group FSM to process this event
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ ret = group_fsm_exec(p_group_inst, &fsm_event);
+ }
+ }
+ while(0);
+
+ return ret;
+}
+
+/*
+ * Helper functions
+ */
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a group instance of the specified
+ * class.
+ *
+ * @param key A pointer to the key of the group being
+ * referenced
+ * @param search_flag A flag specifying the type of group
+ * instance to be retrieved
+ *
+ * @returns group_inst_t* A pointer to the found group instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+static group_inst *group_inst_get(bcmbal_group_key *key, group_flag search_flag)
+{
+ group_inst *current_entry = NULL;
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ if(GROUP_FLAG_ACTIVE & search_flag)
+ {
+ TAILQ_FOREACH(current_entry,
+ &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
+ group_inst_next)
+ {
+
+ if(current_entry->api_req_group_info.key.group_id == key->group_id)
+ {
+ BCM_LOG(DEBUG, log_id_group, "Found active group\n");
+ /* The group instance pointer is in current_entry */
+ break;
+ }
+ }
+ }
+
+ /*
+ * Next, check the free list if the caller has chosen to do so
+ */
+ if((GROUP_FLAG_FREE & search_flag) && (NULL == current_entry))
+ {
+ /* Now check the free list */
+ if(!TAILQ_EMPTY(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list))
+ {
+ /* Just grab the first entry */
+ current_entry = TAILQ_FIRST(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list);
+
+ /* Remove it from the free list */
+ TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list, current_entry, group_inst_next);
+
+ /* And add it to the active list */
+ TAILQ_INSERT_TAIL(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list, current_entry, group_inst_next);
+
+ /*
+ * Initialize the fsm state
+ */
+ current_entry->fsm_state = GROUP_FSM_STATE_NULL;
+
+ BCM_LOG(DEBUG, log_id_group, "Using new group\n");
+
+ }
+ }
+
+ if((GROUP_FLAG_ANY & search_flag) && (NULL == current_entry))
+ {
+ /*A group was not found on either list*/
+
+ BCM_LOG(DEBUG, log_id_group, "************** ERROR: no group found\n");
+ }
+
+ return current_entry;
+}
+
+
+#ifdef GET_GROUP_CFG_BY_KEY_SUPPORTED
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve the current group info for the specified
+ * group instance.
+ *
+ * @param key A group key
+ *
+ * @returns bcmbal_group_cfg* A pointer to the current group info for the
+ * specified group, or NULL if the group is not found
+ *****************************************************************************/
+static bcmbal_group_cfg *group_get_current_info_by_key(bcmbal_group_key key)
+{
+ group_inst *current_entry = NULL;
+
+ /*
+ * Check the active list
+ */
+ TAILQ_FOREACH(current_entry,
+ &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
+ group_inst_next)
+ {
+
+ if(current_entry->current_group_info.key.group_id == key.group_id)
+ {
+ /* The group instance pointer is in current_entry */
+ break;
+ }
+ }
+
+ if(current_entry)
+ {
+ return &(current_entry->current_group_info);
+ }
+ else
+ {
+ return NULL;
+ }
+}
+#endif
+
+/*****************************************************************************/
+/**
+ * @brief A function to free a group instance specified by a the supplied
+ * entry pointer.
+ *
+ * @param p_entry A pointer to the entry to be freed
+ *
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno group_free_by_entry(group_inst *p_entry)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ group_inst *current_entry;
+ group_inst *p_temp_entry;
+
+ /*
+ * First, check the active list (an active group can be in the adding or removing state)
+ */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list,
+ group_inst_next,
+ p_temp_entry)
+ {
+ if(current_entry == p_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&GROUP_FSM_GROUP_LIST_CTX_PTR->active_group_list, current_entry, group_inst_next);
+ break;
+ }
+ }
+
+ /* And add it to the free list */
+ p_entry->fsm_state = GROUP_FSM_STATE_NULL;
+
+ /* And initialize the current object in the group instance */
+ group_inst_entry_obj_init(p_entry);
+
+ TAILQ_INSERT_TAIL(&GROUP_FSM_GROUP_LIST_CTX_PTR->free_group_list, p_entry, group_inst_next);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to remove group members specified in a requested group
+ * from a target group
+ *
+ * @param p_req_group A pointer to the group config that holds the members to be removed
+ * @param p_cur_group A pointer to the group config that holds the current members
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno bcmbal_group_object_member_remove(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group)
+{
+ int i, j, k, num_members, member_match;
+ bcmbal_group_member_info *p_new_member_info;
+ bcmbal_group_member_info_list_u16 new_members;
+
+ num_members = 0;
+ /* first calculate the final number of members */
+ for(i = 0; i < p_cur_group->data.members.len; i++)
+ {
+ member_match = 0;
+ /* check if it is in the remove list */
+ for(j = 0; j < p_req_group->data.members.len; j++)
+ {
+ if( p_cur_group->data.members.val[i].intf_id == p_req_group->data.members.val[j].intf_id)
+ {
+ member_match = 1;
+ break;
+ }
+ }
+ /* no match, we need to keep it */
+ if(!member_match)
+ {
+ num_members++;
+ }
+ }
+ /* if all requested members already been removed, no change, just return */
+ if( num_members == p_cur_group->data.members.len)
+ {
+ return BCM_ERR_OK;
+ }
+ /* if no member left, just clean up and leave */
+ if(num_members == 0)
+ {
+ bcmos_free(p_cur_group->data.members.val);
+ BCMBAL_CFG_PROP_CLEAR(p_cur_group, group, members);
+ return BCM_ERR_OK;
+ }
+
+ /* alloc memory for new list */
+ p_new_member_info = bcmos_calloc( num_members * sizeof(bcmbal_group_member_info));
+ if(p_new_member_info == NULL)
+ {
+ BCM_LOG(ERROR, log_id_group, "calloc failed when remove members from group object\n");
+ return BCM_ERR_NORES;
+ }
+
+ /* fill in the new list */
+ k=0;
+ for(i = 0; i < p_cur_group->data.members.len; i++)
+ {
+ member_match = 0;
+ /* check if it is in the remove list */
+ for(j = 0; j < p_req_group->data.members.len; j++)
+ {
+ if( p_cur_group->data.members.val[i].intf_id == p_req_group->data.members.val[j].intf_id)
+ {
+ member_match = 1;
+ break;
+ }
+ }
+ /* no match, we need to keep it */
+ if(!member_match)
+ {
+ p_new_member_info[k++] = p_cur_group->data.members.val[i];
+ }
+ }
+
+ /* free up the old list */
+ bcmos_free(p_cur_group->data.members.val);
+
+ /* assign new list */
+ new_members.val = p_new_member_info;
+ new_members.len = num_members;
+ BCMBAL_CFG_PROP_SET(p_cur_group, group, members, new_members);
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to add group members specified in a requested group
+ * to a target group
+ *
+ * @param p_req_group A pointer to the group config that holds the members to be added
+ * @param p_cur_group A pointer to the group config that holds the current members
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno bcmbal_group_object_member_add(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group)
+{
+ int i, j, k, num_members, member_match;
+ bcmbal_group_member_info *p_new_member_info;
+ bcmbal_group_member_info_list_u16 new_members;
+
+ num_members = 0;
+ /* first calculate the final number of members */
+ for(i = 0; i < p_req_group->data.members.len; i++)
+ {
+ member_match = 0;
+ /* check if it is in the current list */
+ for(j = 0; j < p_cur_group->data.members.len; j++)
+ {
+ if( p_req_group->data.members.val[i].intf_id == p_cur_group->data.members.val[j].intf_id)
+ {
+ member_match = 1;
+ break;
+ }
+ }
+ /* no match, we need to add it */
+ if(!member_match)
+ {
+ num_members++;
+ }
+ }
+ /* if all requested members already in the list, no change, just return */
+ if( num_members == 0)
+ {
+ return BCM_ERR_OK;
+ }
+ /* alloc memory for new list */
+ p_new_member_info = bcmos_calloc( (num_members + p_cur_group->data.members.len) * sizeof(bcmbal_group_member_info) );
+ if(p_new_member_info == NULL)
+ {
+ BCM_LOG(ERROR, log_id_group, "calloc failed when add members to group object\n");
+ return BCM_ERR_NORES;
+ }
+
+ /* fill in the new list */
+ k=0;
+ for(j = 0; j < p_cur_group->data.members.len; j++)
+ {
+ p_new_member_info[k++] = p_cur_group->data.members.val[j];
+ }
+
+ for(i = 0; i < p_req_group->data.members.len; i++)
+ {
+ member_match = 0;
+ /* check if it is in the current list */
+ for(j = 0; j < p_cur_group->data.members.len; j++)
+ {
+ if( p_req_group->data.members.val[i].intf_id == p_cur_group->data.members.val[j].intf_id)
+ {
+ member_match = 1;
+ break;
+ }
+ }
+ /* no match, we need to add it */
+ if(!member_match)
+ {
+ p_new_member_info[k++] = p_req_group->data.members.val[i];
+ }
+ }
+
+ /* free up the old list */
+ bcmos_free(p_cur_group->data.members.val);
+
+ /* assign new list */
+ new_members.val = p_new_member_info;
+ new_members.len = k;
+ BCMBAL_CFG_PROP_SET(p_cur_group, group, members, new_members);
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to replace group members specified in a targeted group
+ * with a requested group
+ *
+ * @param p_req_group A pointer to the group config that holds the members to be replaced
+ * @param p_cur_group A pointer to the group config that holds the current members
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno bcmbal_group_object_member_replace(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group)
+{
+ int j, k;
+ bcmbal_group_member_info *p_new_member_info;
+ bcmbal_group_member_info_list_u16 new_members;
+
+ /* alloc memory for new list */
+ p_new_member_info = bcmos_calloc( p_req_group->data.members.len * sizeof(bcmbal_group_member_info) );
+ if(p_new_member_info == NULL)
+ {
+ BCM_LOG(ERROR, log_id_group, "calloc failed when replace members to group object\n");
+ return BCM_ERR_NORES;
+ }
+
+ /* fill in the new list */
+ k=0;
+ for(j = 0; j < p_req_group->data.members.len; j++)
+ {
+ p_new_member_info[k++] = p_req_group->data.members.val[j];
+ }
+
+ /* free up the old list */
+ bcmos_free(p_cur_group->data.members.val);
+
+ /* assign new list */
+ new_members.val = p_new_member_info;
+ new_members.len = k;
+ BCMBAL_CFG_PROP_SET(p_cur_group, group, members, new_members);
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to overlay group info specified in a requested group
+ * to a target group ( exclude the member info as it will be managed by
+ bcmbal_group_object_member_xxx functions)
+ *
+ * @param p_req_group A pointer to the requested group config
+ * @param p_cur_group A pointer to the group config that to be overlay
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno bcmbal_group_object_overlay(bcmbal_group_cfg *p_req_group,
+ bcmbal_group_cfg *p_cur_group)
+{
+ BUG_ON(NULL == p_cur_group);
+ BUG_ON(NULL == p_req_group);
+
+ bcmbal_presence_mask cur_presence_mask;
+
+ /* First, copy the common object and keys in their entirety, except for preserving the presence_mask */
+ cur_presence_mask = p_cur_group->hdr.hdr.presence_mask;
+ p_cur_group->hdr = p_req_group->hdr;
+ p_cur_group->key = p_req_group->key;
+ p_cur_group->hdr.hdr.presence_mask = cur_presence_mask;
+
+ /* Now copy only the fields that have been specified in the request object */
+ if(BCMBAL_CFG_PROP_IS_SET(p_req_group, group, members_cmd))
+ {
+ BCMBAL_CFG_PROP_SET(p_cur_group, group, members_cmd, p_req_group->data.members_cmd);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(p_req_group, group, cookie))
+ {
+ BCMBAL_CFG_PROP_SET(p_cur_group, group, cookie, p_req_group->data.cookie);
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(p_req_group, group, owner))
+ {
+ BCMBAL_CFG_PROP_SET(p_cur_group, group, owner, p_req_group->data.owner);
+ }
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to test if the specified group is active
+ *
+ * @param p_group_key A pointer to the group key to be tested
+ *
+ * @returns bcmos_bool BCMOS_TRUE if specified group is active
+ *****************************************************************************/
+bcmos_bool group_is_active(bcmbal_group_key *p_group_key)
+{
+ return (NULL == group_inst_get(p_group_key, GROUP_FLAG_ACTIVE)) ? BCMOS_FALSE : BCMOS_TRUE;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrive the group owner
+ *
+ * @param group_key the group key
+ * @param p_group_owner A pointer to store the retrieve owner
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno group_owner_get(bcmbal_group_key group_key, bcmbal_group_owner *p_group_owner)
+{
+ group_inst *p_group;
+
+ p_group = group_inst_get(&group_key, GROUP_FLAG_ACTIVE);
+ if (p_group)
+ {
+ *p_group_owner = p_group->current_group_info.data.owner;
+ return BCM_ERR_OK;
+ }
+ else
+ {
+ return BCM_ERR_NOENT;
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to set the group owner
+ * When the owner is set, the service port of the member is also allocated
+ *
+ * @param group_key group key
+ * @param grp_owner owner
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno group_owner_set(bcmbal_group_key group_key, bcmbal_group_owner grp_owner)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* if group has no owner, set the GROUP owner and allocate the GEM for each GROUP member
+
+ 1. flip the current info with request info
+ 2. allocate GEM for each group member
+ 3. Call switch_util to update the group (SET with new GEM info)
+ 4. Call mac_util to update the group (SET with new GEM info)
+ 5. flip back the current info
+ else
+ do nothing and let util validate the group owner
+ end-if
+ later, follow the regular FLOW fsm to SET FLOW in switch_util and Mac_util
+ */
+
+ group_inst *p_group;
+
+ p_group = group_inst_get(&group_key, GROUP_FLAG_ACTIVE);
+
+ if (p_group == NULL)
+ {
+ BCM_LOG(ERROR, log_id_group, "Failed to get group instance, group_id %d\n", group_key.group_id);
+ return BCM_ERR_INTERNAL;
+ }
+ if ( BCMBAL_GROUP_OWNER_NONE == p_group->current_group_info.data.owner)
+ {
+ int i;
+ bcmbal_group_cfg *p_group_req = &(p_group->api_req_group_info);
+ bcmbal_group_cfg *p_group_cur = &(p_group->current_group_info);
+
+ do
+ {
+ /* step 1 */
+ BCMBAL_CFG_PROP_SET(p_group_req, group, owner, grp_owner);
+ BCMBAL_CFG_PROP_SET(p_group_req, group, members_cmd, BAL_UTIL_OPER_GROUP_SET);
+ p_group_req->data.members.len = p_group_cur->data.members.len;
+ p_group_req->data.members.val = p_group_cur->data.members.val;
+
+ p_group_cur->data.members.len = 0;
+ p_group_cur->data.members.val = NULL;
+
+ /* step 2 */
+ for(i=0; i<p_group_req->data.members.len; i++)
+ {
+ if(grp_owner == BCMBAL_GROUP_OWNER_UNICAST )
+ {
+ ret = rsc_mgr_gem_alloc_broadcast(p_group_req->data.members.val[i].intf_id,
+ &p_group_req->data.members.val[i].svc_port_id,
+ 1, /* request gem range */
+ NULL);
+ }
+ else if (grp_owner == BCMBAL_GROUP_OWNER_MULTICAST)
+ {
+ ret = rsc_mgr_gem_alloc_multicast(p_group_req->data.members.val[i].intf_id,
+ &p_group_req->data.members.val[i].svc_port_id,
+ 1, /* request gem range */
+ NULL);
+ }
+ else
+ {
+ ret = BCM_ERR_PARM;
+ }
+ if(BCM_ERR_OK != ret)
+ {
+ break;
+ }
+ }
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_group, "Failed to alloc group GEM, interface=%d\n", p_group_req->data.members.val[i].intf_id);
+ break;
+ }
+ /* step 3 */
+ if(BCM_ERR_OK != (ret = sw_util_group_set(p_group, BAL_UTIL_OPER_GROUP_SET)))
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "error %s while updating group GEM in switch\n", bcmos_strerror(ret));
+ break;
+ }
+ /* step 4 - request no indicaiton send back */
+ if(BCM_ERR_OK != (ret = mac_util_group_set(p_group, BAL_UTIL_OPER_GROUP_SET, BCMOS_FALSE)))
+ {
+ BCM_LOG(ERROR, log_id_group,
+ "error %s while updating group GEM in mac \n", bcmos_strerror(ret));
+ break;
+ }
+ /* step 5 - flip back */
+ BCMBAL_CFG_PROP_SET(p_group_cur, group, owner, grp_owner);
+ BCMBAL_CFG_PROP_SET(p_group_cur, group, members_cmd, BAL_UTIL_OPER_GROUP_SET);
+ p_group_cur->data.members.len = p_group_req->data.members.len;
+ p_group_cur->data.members.val = p_group_req->data.members.val;
+
+ p_group_req->data.members.len = 0;
+ p_group_req->data.members.val = NULL;
+
+ }while(0);
+ }
+ else
+ {
+ /* if GROUP already has owner , make sure it is the same type */
+ if ( grp_owner != p_group->current_group_info.data.owner)
+ {
+ BCM_LOG(ERROR, log_id_group,
+ " group already has owner %d, can not reassign to %d \n", p_group->current_group_info.data.owner, grp_owner);
+ ret = BCM_ERR_INTERNAL;
+ }
+ }
+
+ return ret;
+}
+/*@}*/
diff --git a/bal_release/src/core/main/group_fsm.h b/bal_release/src/core/main/group_fsm.h
new file mode 100644
index 0000000..f7ebe57
--- /dev/null
+++ b/bal_release/src/core/main/group_fsm.h
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file group_fsm.h
+ * @brief Code to support the BAL Group FSM
+ *
+ */
+
+#ifndef GROUP_FSM_H
+#define GROUP_FSM_H
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bal_api.h>
+
+/* set the total number of available group to 4k */
+#define GROUP_ALLOCATION_BLOCK_SIZE (4095)
+
+typedef enum
+{
+ GROUP_FSM_EVENT_TYPE_NONE = -1,
+ GROUP_FSM_EVENT_TYPE_CREATE ,
+ GROUP_FSM_EVENT_TYPE_DESTROY ,
+ GROUP_FSM_EVENT_TYPE_ADD ,
+ GROUP_FSM_EVENT_TYPE_REMOVE ,
+ GROUP_FSM_EVENT_TYPE_SET ,
+ GROUP_FSM_EVENT_TYPE_UTIL_MSG ,
+
+ GROUP_FSM_EVENT_TYPE__LAST,
+ GROUP_FSM_EVENT_TYPE__NUM_OF
+} group_fsm_event_type;
+
+
+
+typedef enum
+{
+ GROUP_FSM_STATE_NONE = -1,
+ GROUP_FSM_STATE_NULL ,
+ GROUP_FSM_STATE_CONFIGURING ,
+ GROUP_FSM_STATE_CONFIGURED ,
+ GROUP_FSM_STATE_DELETING ,
+
+ GROUP_FSM_STATE__LAST,
+ GROUP_FSM_STATE__NUM_OF
+} group_fsm_state;
+
+
+typedef enum
+{
+ GROUP_FLAG_ACTIVE = 1<<0, /**< A group is on the active list */
+ GROUP_FLAG_FREE = 1<<1, /**< A group is on the free list */
+ GROUP_FLAG_ANY = (GROUP_FLAG_ACTIVE | GROUP_FLAG_FREE), /**< A group is on either the active or free list */
+} group_flag;
+
+
+typedef struct group_fsm_event_t
+{
+ group_fsm_event_type event_type; /**< The group fsm events */
+ void *msg;
+
+ /* other necessary information */
+} group_fsm_event;
+
+
+typedef struct group_inst group_inst;
+struct group_inst
+{
+ bcmbal_group_cfg current_group_info; /**< The current information for this group (used for GET) */
+ bcmbal_group_cfg api_req_group_info; /**< The last group object info received from the Public API */
+ group_fsm_state fsm_state; /**< The group FSM state */
+ bcmos_timer timer_info; /**< A structure used for the state machine timeout timer */
+ TAILQ_ENTRY(group_inst) group_inst_next ; /**< TAILQ link */
+};
+
+
+/*
+ * Group FSM data structures
+ */
+typedef struct group_fsm_ctx
+{
+ /* Lists of free group entries and active group entries
+ */
+ TAILQ_HEAD(free_group_list_head, group_inst) free_group_list;
+
+ TAILQ_HEAD(active_group_list_head, group_inst) active_group_list;
+
+} group_fsm_ctx;
+
+
+/* Function declarations */
+
+extern bcmos_errno group_fsm_init(void);
+extern bcmos_errno group_fsm_finish(void);
+extern bcmos_errno process_group_util_msg(void *msg_payload);
+extern bcmos_errno process_group_object(void *msg_payload);
+extern bcmos_bool group_is_active(bcmbal_group_key *p_group_key);
+extern bcmos_errno group_owner_set(bcmbal_group_key group_key, bcmbal_group_owner group_owner);
+extern bcmos_errno group_owner_get(bcmbal_group_key group_key, bcmbal_group_owner *p_group_owner);
+
+/*@}*/
+
+#endif /*GROUP_FSM_H */
+
diff --git a/bal_release/src/core/main/sub_term_fsm.c b/bal_release/src/core/main/sub_term_fsm.c
new file mode 100644
index 0000000..c632a28
--- /dev/null
+++ b/bal_release/src/core/main/sub_term_fsm.c
@@ -0,0 +1,2182 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file sub_term_fsm.c
+ * @brief Code to support the BAL subscriber-terminal FSM
+ *
+ * @addtogroup sub_terminal
+ *
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bal_msg.h>
+#include <bal_osmsg.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include "sub_term_fsm.h"
+#include "tm_sched_fsm.h"
+
+#include <bal_objs.h>
+#include <fsm_common.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+/*
+ * @brief Logging device id for the subscriber-terminal
+ */
+static dev_log_id log_id_sub_term;
+#endif
+
+/* local function declarations */
+
+static bcmos_errno sub_term_fsm_admin_up_start(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_admin_up_error(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_admin_dn_start(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_admin_dn_ok(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_admin_dn_error(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_removing_start(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_ignore_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+
+static bcmos_errno sub_term_fsm_removing_process_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_removing_process_util_auto_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_configuring_process_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_null_process_util_auto_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_configured_process_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_configuring_process_util_auto_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_state_err(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_fsm_exec(sub_term_inst *p_sub_term_inst, sub_term_fsm_event *p_event);
+
+static bcmos_errno sub_term_free_by_entry(sub_term_inst *p_entry);
+
+
+static bcmos_errno agg_port_id_list_fill(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id_list_u8 *agg_port_id_list);
+
+static bcmos_errno svc_port_id_list_fill(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id_list_u8 *svc_port_id_list);
+
+static bcmos_errno bcmbal_sub_term_tm_scheds_set(const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg);
+
+/*
+ *@brief Global sub_term fsm context data structure
+ */
+static sub_term_fsm_ctx g_sub_term_fsm_sub_term_list_ctx;
+
+/*
+ * Macros for sub_term ctx access
+ */
+#define SUB_TERM_FSM_SUB_TERM_LIST_CTX (g_sub_term_fsm_sub_term_list_ctx)
+#define SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR (&g_sub_term_fsm_sub_term_list_ctx)
+
+/*
+ * @brief The definition of a sub_term state processing function
+ */
+typedef bcmos_errno (* sub_term_fsm_state_processor)(sub_term_inst *, void *, sub_term_fsm_event *);
+
+/*
+ * @brief The Subscriber Terminal FSM state processing array
+ */
+static sub_term_fsm_state_processor sub_term_states[SUB_TERM_FSM_STATE__NUM_OF][SUB_TERM_FSM_EVENT_TYPE__NUM_OF] =
+{
+
+ [SUB_TERM_FSM_STATE_NULL] =
+ {
+ /*
+ * Next state: CONFIGURING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_start,
+
+ /*
+ * Next state: NULL
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_ok,
+
+ /*
+ * Next state: NULL
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_ignore_util_msg,
+
+ /*
+ * Next state: NULL
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_null_process_util_auto_msg,
+ },
+
+ [SUB_TERM_FSM_STATE_CONFIGURING] =
+ {
+ /*
+ * Next state: CONFIGURING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_error,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_error,
+
+ /*
+ * Next state: REMOVING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_REMOVE] = sub_term_fsm_removing_start,
+
+ /*
+ * Next state: CONFIGURING | CONFIGURED
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_configuring_process_util_msg,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_configuring_process_util_auto_msg,
+
+ },
+
+ [SUB_TERM_FSM_STATE_CONFIGURED] =
+ {
+ /*
+ * Next state: CONFIGURED
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_start,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_start,
+
+ /*
+ * Next state: REMOVING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_REMOVE] = sub_term_fsm_removing_start,
+
+ /*
+ * Next state: CONFIGURING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_configured_process_util_msg,
+
+ /*
+ * Next state: CONFIGURED
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_ignore_util_msg,
+
+ },
+
+ [SUB_TERM_FSM_STATE_REMOVING] =
+ {
+ /*
+ * Next state: REMOVING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_error,
+
+ /*
+ * Next state: REMOVING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_error,
+
+ /*
+ * Next state: REMOVING | NULL
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_removing_process_util_msg,
+
+ /*
+ * Next state: REMOVING
+ */
+ [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_removing_process_util_auto_msg,
+ },
+};
+
+static char *state_name_str[] =
+{
+ "SUB_TERM_FSM_STATE_NULL",
+ "SUB_TERM_FSM_STATE_CONFIGURING",
+ "SUB_TERM_FSM_STATE_CONFIGURED",
+ "SUB_TERM_FSM_STATE_REMOVING",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (SUB_TERM_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), sub_term_fsm_state);
+
+static char *sub_term_state_name_get(sub_term_fsm_state state)
+{
+ if(state < SUB_TERM_FSM_STATE__LAST)
+ {
+ return state_name_str[state];
+ }
+ else
+ {
+ return "SUB_TERM_UNKNOWN";
+ }
+}
+
+static char *event_name_str[] =
+{
+ "SUB_TERM_FSM_ADMIN_UP_EVENT",
+ "SUB_TERM_FSM_ADMIN_DN_EVENT",
+ "SUB_TERM_FSM_REMOVE_EVENT",
+ "SUB_TERM_FSM_UTIL_MSG_EVENT",
+ "SUB_TERM_FSM_UTIL_AUTO_IND_EVENT",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT (SUB_TERM_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), sub_term_fsm_event_type);
+
+static char *sub_term_event_name_get(sub_term_fsm_event_type event)
+{
+ if(event < SUB_TERM_FSM_EVENT_TYPE__LAST)
+ {
+ return event_name_str[event];
+ }
+ else
+ {
+ return "SUB_TERM_EVT_UNKNOWN";
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the current sub_term_info object of the
+ * supplied entry.
+ *
+ * @param p_entry A pointer to the entry to be initialized
+ *
+ *
+ * @returns void
+ *****************************************************************************/
+static void sub_term_inst_entry_obj_init(sub_term_inst *p_entry)
+{
+ bcmbal_subscriber_terminal_key key = { .sub_term_id = 0, .intf_id = 0 };
+ BCMBAL_CFG_INIT(&p_entry->current_sub_term_info,
+ subscriber_terminal,
+ key);
+
+ BCMBAL_CFG_PROP_SET(&p_entry->current_sub_term_info,
+ subscriber_terminal, admin_state, BCMBAL_STATE_DOWN);
+
+ BCMBAL_CFG_PROP_SET(&p_entry->current_sub_term_info,
+ subscriber_terminal, oper_status, BCMBAL_STATUS_NOT_PRESENT);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_sub_term_info), BCMOS_FALSE);
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function called to initialize the subscriber-terminal FSM
+ * infrastructure.
+ *
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @returns void
+ *****************************************************************************/
+bcmos_errno sub_term_fsm_init(void)
+{
+ int ii;
+ sub_term_inst *new_entry;
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifdef ENABLE_LOG
+ log_id_sub_term = bcm_dev_log_id_register("SUB_TERM", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_sub_term == DEV_LOG_INVALID_ID);
+#endif
+
+ /* Initialize all of the sub_term queues */
+ TAILQ_INIT(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list);
+ TAILQ_INIT(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list);
+
+ /* Populate the free list with it's set of sub_term instance entries */
+ for(ii=0; ii<NUM_SUPPORTED_SUB_TERMS; ii++)
+ {
+
+ new_entry = bcmos_calloc(sizeof(sub_term_inst));
+
+ if (NULL == new_entry)
+ {
+ BCM_LOG(FATAL, log_id_sub_term,
+ "Failed to initialize the sub_term free list - FATAL\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ /* And add it to the free list */
+ sub_term_free_by_entry(new_entry);
+
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to un-initialize the subscriber-terminal FSM infrastructure.
+ *
+ * NOTE: This is called once on shutdown and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno sub_term_fsm_finish(void)
+{
+
+ sub_term_inst *current_entry, *p_temp_entry;
+ agg_port_id_entry *agg_port_entry;
+ svc_port_id_entry *svc_port_entry;
+
+ /* Free all the entries on the active list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list,
+ sub_term_inst_next,
+ p_temp_entry)
+ {
+ /* free the aggregation port list */
+ TAILQ_FOREACH(agg_port_entry,
+ ¤t_entry->agg_port_id_list,
+ next)
+ {
+
+ bcmos_free(agg_port_entry);
+ }
+
+ /* free the service port list */
+ TAILQ_FOREACH(svc_port_entry,
+ ¤t_entry->svc_port_id_list,
+ next)
+ {
+ bcmos_free(svc_port_entry);
+ }
+
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list,
+ current_entry, sub_term_inst_next);
+
+ bcmos_free(current_entry);
+
+ }
+
+ /* Free all the entries on the free list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list,
+ sub_term_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list,
+ current_entry, sub_term_inst_next);
+
+ bcmos_free(current_entry);
+
+ }
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing executive function
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_exec(sub_term_inst *p_sub_term_inst, sub_term_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ sub_term_fsm_state pre_state;
+ sub_term_fsm_state fsm_state;
+ sub_term_fsm_state_processor sub_term_state_processor;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_event);
+
+ /* Record the present state for debug printing
+ */
+ pre_state = (NULL == p_sub_term_inst) ? SUB_TERM_FSM_STATE_NULL : p_sub_term_inst->fsm_state;
+
+ /*
+ * Get the state processing function
+ */
+ sub_term_state_processor = sub_term_states[pre_state][p_event->event_type];
+
+ /*
+ * If there's a state processing function for this event and state, execute it.
+ * Otherwise, process a generic error.
+ */
+ if (sub_term_state_processor)
+ {
+ ret = sub_term_state_processor(p_sub_term_inst, p_event->msg, p_event);
+ } else
+ {
+ sub_term_fsm_state_err(p_sub_term_inst, p_event->msg, p_event);
+ }
+
+ /* And get the new state for debug printing */
+ fsm_state = (NULL == p_sub_term_inst) ? SUB_TERM_FSM_STATE_NULL : p_sub_term_inst->fsm_state;
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "*** Event %s, State: %s --> %s\n",
+ sub_term_event_name_get(p_event->event_type),
+ sub_term_state_name_get(pre_state), sub_term_state_name_get(fsm_state));
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function called by the core worker thread to process an
+ * subscriber-terminal object message (SET, GET, CLEAR, STATS) received
+ * from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_subscriber_terminal_object(void *msg_payload)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+
+ bcmbal_subscriber_terminal_cfg *p_sub_term_cfg = (bcmbal_subscriber_terminal_cfg *)msg_payload;
+ sub_term_inst *p_sub_term_inst;
+ sub_term_fsm_event fsm_event;
+ bcmbal_subscriber_terminal_key *sub_term_key;
+ bcmbal_obj_msg_type oper_type;
+
+ /* Parameter checks */
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id_sub_term, "Processing a sub_term object\n");
+
+ sub_term_key = &p_sub_term_cfg->key;
+
+ oper_type = p_sub_term_cfg->hdr.hdr.type;
+
+ /*
+ * A message pointer may be passed inside the event structure.
+ */
+ fsm_event.msg = msg_payload;
+
+ /* SET or GET or CLEAR ? */
+ switch (oper_type)
+ {
+ case (BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+ bcmos_bool b_generate_event = BCMOS_FALSE;
+
+ BCM_LOG(DEBUG, log_id_sub_term, "Processing a sub_term SET REQ mgmt message\n");
+
+ /*
+ * Find or create the specified sub_term instance
+ */
+ p_sub_term_inst = sub_term_inst_get(sub_term_key, SUB_TERM_FLAG_ANY);
+
+ do
+ {
+
+ if(NULL == p_sub_term_inst)
+ {
+ /* This is a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Specified sub_term not found. No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ /* If the state of this sub_term is in flux, then reject the SET request */
+ if(BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_sub_term_inst->current_sub_term_info)))
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "The subscriber_terminal is in-progress, SETs are not allowed\n");
+ ret = BCM_ERR_IN_PROGRESS;
+ break;
+ }
+
+ if(BCM_ERR_OK != (ret = bcmbal_sub_term_tm_scheds_set(p_sub_term_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "could not set subscriber terminal as owner of specified tm scheds\n");
+ ret = BCM_ERR_PARM;
+
+ }
+
+ /*
+ * Fill in the local sub_term instance API request data structure
+ */
+ p_sub_term_inst->api_req_sub_term_info = *p_sub_term_cfg;
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "sub_term admin state is: %s\n",
+ (BCMBAL_STATE_UP == p_sub_term_inst->api_req_sub_term_info.data.admin_state) ? "UP" : "DOWN");
+
+
+ /* If there's no state change, then we're done */
+ if(p_sub_term_inst->current_sub_term_info.data.admin_state ==
+ p_sub_term_inst->api_req_sub_term_info.data.admin_state)
+ {
+ break;
+ }
+
+ /* For subscriber terminals that have already been configured and then made dormant, merge the
+ * requested data with the current data, and this is the new request.
+ */
+ if(BCMBAL_STATUS_DOWN == p_sub_term_inst->current_sub_term_info.data.oper_status)
+ {
+
+ bcmbal_sub_term_object_overlay_w_dst_priority(&p_sub_term_inst->api_req_sub_term_info,
+ &p_sub_term_inst->current_sub_term_info);
+ }
+
+ /*
+ * Check if the mandatory subscriber terminal attributes have been set, and range check where
+ * applicable.
+ */
+
+
+ /* The admin state attribute is mandatory */
+ if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(&p_sub_term_inst->api_req_sub_term_info,
+ subscriber_terminal,
+ admin_state))
+ {
+ ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+
+ /*
+ * Perform the validation check(s) that the utils require
+ */
+ if(BCM_ERR_OK !=
+ (ret = mac_util_subscriber_terminal_info_validate(&p_sub_term_inst->api_req_sub_term_info)))
+ {
+ break;
+ }
+
+ }
+ while(0);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term);
+
+ if(BCM_ERR_OK != ret)
+ {
+ break;
+ }
+
+ /*
+ * Initial checks complete. Process the request
+ */
+
+ if((BCMBAL_STATE_UP == p_sub_term_inst->api_req_sub_term_info.data.admin_state)
+ && (BCMBAL_STATE_UP != p_sub_term_inst->current_sub_term_info.data.admin_state))
+ {
+ BCMBAL_CFG_PROP_SET(&p_sub_term_inst->api_req_sub_term_info,
+ subscriber_terminal,
+ svc_port_id,
+ sub_term_key->sub_term_id);
+
+ p_sub_term_inst->api_req_sub_term_info.data.admin_state = BCMBAL_STATE_UP;
+
+ /* Set the expected state of the oper_status upon success */
+ p_sub_term_inst->api_req_sub_term_info.data.oper_status = BCMBAL_STATUS_UP;
+
+ fsm_event.event_type = SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP;
+ b_generate_event = BCMOS_TRUE;
+
+ BCM_LOG(INFO, log_id_sub_term,
+ "***Using GEM %d for subscriber terminal OMCI channel\n",
+ p_sub_term_inst->api_req_sub_term_info.data.svc_port_id);
+
+ }
+ else if((BCMBAL_STATE_DOWN == p_sub_term_inst->api_req_sub_term_info.data.admin_state)
+ && (BCMBAL_STATE_DOWN != p_sub_term_inst->current_sub_term_info.data.admin_state))
+ {
+ p_sub_term_inst->current_sub_term_info.data.admin_state = BCMBAL_STATE_DOWN;
+
+ /* Set the expected state of the oper_status upon success */
+ p_sub_term_inst->api_req_sub_term_info.data.oper_status = BCMBAL_STATUS_DOWN;
+
+ fsm_event.event_type = SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN;
+ b_generate_event = BCMOS_TRUE;
+ }
+ else
+ {
+ /* @todo implement a MODIFY here */
+ BCM_LOG(INFO, log_id_sub_term, "no state change...done\n");
+ break; /* no state change detected - do nothing for now */
+ }
+
+ /* If there was an event generated, call the state machine exec */
+ if(BCMOS_TRUE == b_generate_event)
+ {
+ /*
+ * Run the sub_term FSM to process this event
+ */
+ ret = sub_term_fsm_exec(p_sub_term_inst, &fsm_event);
+ }
+ break;
+ }
+
+ case (BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+
+ bcmbal_aggregation_port_id_list_u8 agg_port_id_list = {};
+ bcmbal_service_port_id_list_u8 svc_port_id_list = {};
+
+ BCM_LOG(DEBUG, log_id_sub_term, "Processing a sub_term GET REQ mgmt message\n");
+
+ /*
+ * Just return the sub_term data info that we have on record for
+ * this sub_term instance
+ */
+
+ /*
+ * Find the specified sub_term instance
+ */
+ p_sub_term_inst = sub_term_inst_get(sub_term_key, SUB_TERM_FLAG_ACTIVE);
+
+ if(NULL == p_sub_term_inst)
+ {
+ /* This is not a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_sub_term, "Specified sub_term not found on GET\n");
+ ret = BCM_ERR_NOENT;
+ }
+ else
+ {
+ do
+ {
+ /* Return the agg_port_id list if requested */
+ BCMBAL_CFG_PROP_CLEAR(&p_sub_term_inst->current_sub_term_info,
+ subscriber_terminal,
+ agg_port_id_list);
+
+
+ /* If the user requested the list of agg_port_ids for this subscriber terminal
+ * then return the list.
+ */
+ if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg,
+ subscriber_terminal,
+ agg_port_id_list))
+ {
+
+ if(BCM_ERR_OK == agg_port_id_list_fill(p_sub_term_inst, &agg_port_id_list))
+ {
+ /* NOTE: The returned list may be empty */
+ BCMBAL_CFG_PROP_SET(&p_sub_term_inst->current_sub_term_info,
+ subscriber_terminal,
+ agg_port_id_list,
+ agg_port_id_list);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sub_term, "Error trying to fill agg_port list to return\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+
+ }
+ }
+
+ /* Return the svc_port_id list if requested */
+ BCMBAL_CFG_PROP_CLEAR(&p_sub_term_inst->current_sub_term_info,
+ subscriber_terminal,
+ svc_port_id_list);
+
+ /* If the user requested the list of sub_term_ids for this subscriber terminal,
+ * then return the list.
+ */
+ if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg,
+ subscriber_terminal,
+ svc_port_id_list))
+ {
+
+ if(BCM_ERR_OK == svc_port_id_list_fill(p_sub_term_inst, &svc_port_id_list))
+ {
+ /* NOTE: The returned list may be empty */
+ BCMBAL_CFG_PROP_SET(&p_sub_term_inst->current_sub_term_info,
+ subscriber_terminal,
+ svc_port_id_list,
+ svc_port_id_list);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sub_term, "Error trying to fill svc_port list to return\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+
+ }
+ }
+ }while (0);
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+
+ p_sub_term_inst->current_sub_term_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+ *((bcmbal_subscriber_terminal_cfg *)msg_payload) = p_sub_term_inst->current_sub_term_info;
+ }
+
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term);
+
+ /* Free the temporary lists if they were used */
+ if(svc_port_id_list.val)
+ {
+ bcmos_free(svc_port_id_list.val);
+ }
+
+ if(agg_port_id_list.val)
+ {
+ bcmos_free(agg_port_id_list.val);
+ }
+
+ break;
+ }
+
+ case (BCMBAL_OBJ_MSG_TYPE_CLEAR):
+ {
+ /*
+ * Find the specified sub_term instance
+ */
+ p_sub_term_inst = sub_term_inst_get(sub_term_key, SUB_TERM_FLAG_ACTIVE);
+
+ if(NULL == p_sub_term_inst)
+ {
+ /* This is not a fatal error condition
+ */
+ BCM_LOG(ERROR, log_id_sub_term, "Specified sub_term not found on CLEAR\n");
+ ret = BCM_ERR_NOENT;
+ }
+ else
+ {
+ /*
+ * Fill in the local sub_term instance API request data structure
+ */
+ p_sub_term_inst->api_req_sub_term_info = *p_sub_term_cfg;
+ }
+
+ /* We respond to the BAL public API backend with a result.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term);
+
+ if(BCM_ERR_OK == ret)
+ {
+ fsm_event.event_type = SUB_TERM_FSM_EVENT_TYPE_REMOVE;
+
+ /* Run the sub_term FSM to process this event */
+ ret = sub_term_fsm_exec(p_sub_term_inst, &fsm_event);
+ }
+
+ break;
+ }
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Unsupported operation on sub_term object (%d)\n",
+ bcmbal_msg_id_oper_get(msg_payload) );
+
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term);
+ break;
+ }
+ }
+
+ return ret;
+}
+
+
+bcmos_errno process_subscriber_terminal_util_msg(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ sub_term_inst *p_sub_term_inst = NULL;
+ bcmbal_msg_type type;
+ sub_term_fsm_event sub_term_event;
+ bcmbal_subscriber_terminal_key key;
+
+ BUG_ON(NULL == msg_payload);
+
+ type = bcmbal_type_minor_get(msg_payload);
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "Processing a sub_term %s util message from %s\n",
+ bcmbal_msg_t_str[type],
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ /* recover the key from the message */
+ key = ((bal_util_msg_ind *)msg_payload)->obj_key.sub_term_key;
+
+ do
+ {
+ BCM_LOG(DEBUG, log_id_sub_term, "Got sub_term key id from util (ID%d, PON %d)\n",
+ key.sub_term_id, key.intf_id);
+
+ /* Don't bother to look up the sub_term instance for DISCOVERY messages from the
+ * mac util where the sub_term_id is unknown. This is a new ONU, so it will not
+ * be found in the ACTIVE table.
+ */
+ if((BAL_MSG_TYPE_AUTO_IND != (bcmbal_msg_type)type) ||
+ (BAL_MSG_TYPE_AUTO_IND == (bcmbal_msg_type)type && BCMBAL_SUB_ID_UNKNOWN != key.sub_term_id))
+ {
+ /*
+ * Get the sub_term instance that's being referenced
+ */
+ p_sub_term_inst = sub_term_inst_get(&key, SUB_TERM_FLAG_ACTIVE);
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "invalid sub_term (ID%d, PON%d) found while processing a util message type %s from %s\n",
+ key.sub_term_id,
+ key.intf_id,
+ bcmbal_msg_t_str[type],
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ ret = BCM_ERR_INTERNAL;
+
+ break;
+ }
+ }
+
+ /*
+ * Record the msg for further processing access
+ */
+ sub_term_event.msg = msg_payload;
+
+ if (BAL_MSG_TYPE_IND == type)
+ {
+ sub_term_event.event_type = SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG;
+ }
+ else if (BAL_MSG_TYPE_AUTO_IND == type)
+ {
+ sub_term_event.event_type = SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG;
+ }
+ else
+ {
+ ret = BCM_ERR_NOT_SUPPORTED;
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Unknown message type received from the APP (not one of RSP:ACK:IND:AUTO_IND) (type:%d)\n",
+ type);
+ }
+
+ if (p_sub_term_inst)
+ {
+ BCM_LOG(DEBUG, log_id_sub_term, "p_sub_term_inst->fsm_state=%d , sub_term_event.event_type = %d\n",
+ p_sub_term_inst->fsm_state, sub_term_event.event_type);
+ }
+ else
+ {
+ if (BAL_MSG_TYPE_IND == type)
+ {
+ BCM_LOG(WARNING, log_id_sub_term, "p_sub_term_inst is NULL\n");
+ }
+ }
+ /*
+ * Run the Sub_Term FSM to process this event
+ */
+ if(BCM_ERR_OK == ret)
+ {
+ ret = sub_term_fsm_exec(p_sub_term_inst, &sub_term_event);
+ }
+ }
+ while(0);
+
+ return ret;
+}
+
+/************************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing for a subscriber-terminal
+ * admin-up command received from the BAL Public API when the specified
+ * subscriber-terminal instance is in the admin-down state (i.e. when
+ * the subscriber-terminal instance FSM is in the NULL or REMOVED state).
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ ***********************************************************************************/
+static bcmos_errno sub_term_fsm_admin_up_start(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_sub_term,
+ "Received a admin UP request from BAL API - bringing up SUB_TERM\n");
+
+ /* change subscriber terminal state to CONFIGURING */
+ p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */
+ ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_ADD, BCMOS_FALSE);
+
+ do
+ {
+
+ /* check for object in wrong state, this is not an actual error */
+ if(BCM_ERR_STATE == ret)
+ {
+ BCM_LOG(INFO, log_id_sub_term,
+ "mac_util_subscriber_terminal_set() subscriber_terminal could not be activated at this time\n");
+
+ }
+ /* check for errors */
+ else if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Error detected in mac_util_subscriber_terminal_set(): %s\n",
+ bcmos_strerror(ret));
+ break;
+
+ }
+
+ /* The hardware has properly accepted the object info, so the request object becomes
+ * the current state, except for the oper_status.
+ */
+ bcmbal_sub_term_object_overlay_w_src_priority(&p_sub_term_inst->current_sub_term_info,
+ &p_sub_term_inst->api_req_sub_term_info);
+
+ /* Add this subscriber_terminal to the list of subscriber_terminals associated with it's interface */
+ bcmbal_interface_sub_term_list_entry_add(p_sub_term_inst->current_sub_term_info.key);
+
+ /* Record that this object is in progress */
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_TRUE);
+
+ } while(0);
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_sub_term);
+ }
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief The subscriber terminal FSM state processing for a subscriber terminal
+ * admin-up command received from the BAL Public API when the specified
+ * subscriber terminal FSM is already in the REMOVING state.
+ *
+ * @param p_sub_term_inst Pointer to a subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_admin_up_error(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_STATE;
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "Received a admin UP request from BAL API - returning ERROR to the API"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing for an subscriber-terminal
+ * admin-down command received from the BAL Public API when the specified
+ * subscriber-terminal is admin-up (i.e when the specified subscriber-terminal
+ * instance FSM is in the CONFIGURED state).
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_admin_dn_start(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_sub_term,
+ "Received a admin DOWN request from BAL API - bringing down SUB_TERM\n");
+
+ /* change subscriber terminal state to CONFIGURING */
+ p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURING;
+
+ /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */
+ ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_REMOVE, BCMOS_FALSE);
+
+ /* check for errors */
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Error detected in mac_util_subscriber_terminal_set(): %s\n",
+ bcmos_strerror(ret));
+
+ /* report the status to the API */
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_sub_term);
+
+
+ }
+ else
+ {
+ /* NOTE: The hardware has properly accepted the object info but we do
+ * not overwrite the current subscriber terminal data as there is nothing in the request
+ * that is relevant besides the admin_state. We merely set the object to in_progress.
+ */
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_TRUE);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing for an subscriber-terminal
+ * clear command received from the BAL Public API
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_removing_start(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_sub_term,
+ "Received a REMOVE request from BAL API - removing SUB_TERM\n");
+
+ /* change subscriber terminal state to REMOVING */
+ p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_REMOVING;
+
+ /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */
+ ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_CLEAR, BCMOS_FALSE);
+
+ /* check for errors */
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Error detected in mac_util_subscriber_terminal_set(): %s\n",
+ bcmos_strerror(ret));
+
+ /* report the error to the API */
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_sub_term);
+ }
+ else
+ {
+ /* The hardware has properly accepted the object info, so the request object becomes
+ * the current state, except for the oper_status.
+ */
+ bcmbal_sub_term_object_overlay_w_src_priority(&p_sub_term_inst->current_sub_term_info,
+ &p_sub_term_inst->api_req_sub_term_info);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_TRUE);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing for subscriber-terminal
+ * admin-down command from the BAL Public API when the specified
+ * subscriber-terminal is already admin-down.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_admin_dn_ok(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "Received a admin DOWN request from BAL API - returning OK to the API"
+ " - no further function\n");
+
+ mgmt_msg_send_balapi_ind(ret,
+ msg,
+ log_id_sub_term);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The subscriber terminal FSM state processing for a subscriber terminal
+ * admin-down command received from the BAL Public API when the specified
+ * subscriber terminal FSM is already in the REMOVING state.
+ *
+ * @param p_sub_term_inst Pointer to a subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_admin_dn_error(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_STATE;
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "Received a admin DOWN request from BAL API - returning ERROR to the API"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to ignore a
+ * received message.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_ignore_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_sub_term, "Ignoring message from BAL utils\n");
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to process an
+ * AUTO IND message from one of the BAL apps while in the NULL state.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_null_process_util_auto_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_subscriber_terminal_cfg subscriber_terminal_obj;
+ bcmbal_serial_number serial = {};
+ bal_util_msg_ind *ind_msg;
+
+ /* Process checks */
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ BCM_LOG(DEBUG, log_id_sub_term, "Received a AUTO IND in the null state\n");
+
+ /*
+ * Set the key in the subscriber_terminal object
+ */
+ BCMBAL_CFG_INIT(&subscriber_terminal_obj, subscriber_terminal, ind_msg->obj_key.sub_term_key);
+
+ /*
+ * Set the serial number in the subscriber_terminal object
+ */
+ memcpy(&serial, ind_msg->data, sizeof(bcmbal_serial_number));
+ BCMBAL_CFG_PROP_SET(&subscriber_terminal_obj, subscriber_terminal, serial_number, serial);
+
+ /* And mark it's status as DOWN */
+ BCMBAL_CFG_PROP_SET(&subscriber_terminal_obj, subscriber_terminal, oper_status, BCMBAL_STATUS_DOWN);
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&subscriber_terminal_obj.hdr,
+ log_id_sub_term);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to process an
+ * AUTO IND message from one of the BAL apps while in the CONFIGURING state.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_configuring_process_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_sub_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ " Received a IND message from BAL UTIL (%s) during CONFIGURING state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ /* Handle response */
+ ret = ind_msg->status;
+
+ if(BCM_ERR_OK == ret)
+ {
+
+ /* If this indication is for a subscriber terminal that has been ADDED and is ADMIN_UP,
+ * OR for a subscriber terminal that has been REMOVED and is ADMIN_DOWN
+ * then complete the state transition.
+ */
+
+ if((BAL_UTIL_OPER_SUB_TERM_ADD == bcmbal_msg_id_oper_get(msg) &&
+ BCMBAL_STATE_UP == p_sub_term_inst->current_sub_term_info.data.admin_state) ||
+ (BAL_UTIL_OPER_SUB_TERM_REMOVE == bcmbal_msg_id_oper_get(msg) &&
+ BCMBAL_STATE_DOWN == p_sub_term_inst->current_sub_term_info.data.admin_state))
+ {
+
+ if (bcm_topo_pon_get_pon_family(p_sub_term_inst->current_sub_term_info.key.intf_id) == BCM_TOPO_PON_FAMILY_EPON)
+ {
+ uint16_t tunnel_id;
+
+ /* Recover the tunnel_id from the indication message */
+ memcpy(&tunnel_id, ind_msg->data, sizeof(tunnel_id));
+
+ /* And store it in the sub_term instance, to be used by the switch */
+ p_sub_term_inst->current_sub_term_info.data.svc_port_id = tunnel_id;
+ }
+
+ p_sub_term_inst->current_sub_term_info.data.oper_status =
+ p_sub_term_inst->api_req_sub_term_info.data.oper_status;
+
+ /*
+ * The subscriber terminal has been successfully configured
+ */
+ p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURED;
+
+ }
+
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Failed in state %s;%s\n",
+ sub_term_state_name_get(p_sub_term_inst->fsm_state),
+ bcmos_strerror(ret));
+ }
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_FALSE);
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&p_sub_term_inst->current_sub_term_info.hdr,
+ log_id_sub_term);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to process an
+ * IND message from one of the BAL apps while in the CONFIGURED state.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_configured_process_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Process checks */
+ BUG_ON(NULL == p_sub_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ " Received a IND message from BAL UTIL (%s) during CONFIGURED state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ if((BAL_UTIL_OPER_SUB_TERM_REMOVE != bcmbal_msg_id_oper_get(msg)) &&
+ (BAL_UTIL_OPER_SUB_TERM_CLEAR != bcmbal_msg_id_oper_get(msg)))
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Received an unrecognized IND (%u) received in the configured state"
+ "- no further function\n", bcmbal_msg_id_oper_get(msg));
+ }
+ else
+ {
+
+
+ /* change subscriber terminal state to CONFIGURING */
+ p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURING;
+
+ /* Set the oper_status upon success */
+ p_sub_term_inst->current_sub_term_info.data.oper_status = BCMBAL_STATUS_NOT_PRESENT;
+
+ /*
+ * Send the indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_sub_term_inst->current_sub_term_info.hdr,
+ log_id_sub_term);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to process an
+ * AUTO IND message from one of the BAL apps while in the CONFIGURED state.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_configuring_process_util_auto_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Process checks */
+ BUG_ON(NULL == p_sub_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ " Received a AUTO IND message from BAL UTIL (%s) during CONFIGURING state\n",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ if(BAL_UTIL_OPER_SUB_TERM_DISCOVERY != bcmbal_msg_id_oper_get(msg))
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Received an unrecognized AUTO IND in the configuring state"
+ "- no further function\n");
+ }
+ else
+ {
+ /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */
+ /* send TRUE in last argument to indicate the request is after a ONU Discovery */
+ ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_ADD, BCMOS_TRUE);
+ }
+
+ /* If there were errors during processing, then report the error to the API */
+ if(BCM_ERR_OK != ret)
+ {
+
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&p_sub_term_inst->current_sub_term_info.hdr,
+ log_id_sub_term);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to process a
+ * message from one of the BAL apps while in the REMOVING state.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_removing_process_util_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_sub_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ /*
+ * NOTE: AUTO_IND messages are not processed in this function,
+ * so there is no need to consider them in this logic.
+ */
+
+ /* Handle indication */
+ ret = ind_msg->status;
+
+ BCM_LOG(INFO, log_id_sub_term,
+ "Received a %s message from BAL APP (%s) during REMOVING state\n",
+ (BAL_MSG_TYPE_IND == bcmbal_type_minor_get(msg)) ? "IND" : "RSP",
+ subsystem_str[bcmbal_sender_get(msg)]);
+
+ if(BCM_ERR_OK == ret)
+ {
+ /* Set the admin_state and oper_status to be DOWN and NOT_PRESENT respectively,
+ * since we are clearing this object anyway. These parameters are set in the free function,
+ * but they need to be set here for the indication below to be correct */
+ p_sub_term_inst->current_sub_term_info.data.admin_state = BCMBAL_STATE_DOWN;
+ p_sub_term_inst->current_sub_term_info.data.oper_status = BCMBAL_STATUS_NOT_PRESENT;
+ }
+
+ if(BCM_ERR_OK == ret)
+ {
+
+ /* Remove this subscriber_terminal from the list of subscriber_terminals associated with it's interface */
+ bcmbal_interface_sub_term_list_entry_remove(p_sub_term_inst->current_sub_term_info.key);
+
+ /*
+ * Send the success indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_sub_term_inst->current_sub_term_info.hdr,
+ log_id_sub_term);
+
+ /* Return the subscriber terminal to the free pool */
+ sub_term_free_by_entry(p_sub_term_inst);
+
+ BCM_LOG(DEBUG, log_id_sub_term, "sub term freed\n");
+
+ }
+ else
+ {
+ p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURED;
+
+ /*
+ * Send the failure indication back to the BAL public API here
+ */
+ mgmt_msg_send_balapi_ind(ret,
+ &p_sub_term_inst->current_sub_term_info.hdr,
+ log_id_sub_term);
+
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Error encountered in REMOVING state (status is %s)\n",
+ bcmos_strerror(ret));
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM state processing function to process an
+ * AUTO IND message from one of the BAL apps while in the REMOVING state.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_removing_process_util_auto_msg(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_sub_term_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ BCM_LOG(DEBUG, log_id_sub_term,
+ "Received a AUTO IND in the removing state"
+ " - no further function\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Subscriber terminal FSM function which is executed when an error
+ * is encountered during FSM processing.
+ *
+ * @param p_sub_term_inst Pointer to an subscriber terminal instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps
+ * @param p_event Pointer to an subscriber terminal event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_fsm_state_err(sub_term_inst *p_sub_term_inst,
+ void *msg,
+ sub_term_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_INVALID_OP;
+
+ BCM_LOG(ERROR, log_id_sub_term,
+ "Error encountered processing SUB_TERM FSM - BAD EVENT ()\n");
+
+ return ret;
+}
+
+
+/*
+ * Helper functions
+ */
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a subscriber-terminal instance of the specified
+ * class.
+ *
+ * @param key A pointer to the key of the subscriber-terminal being
+ * referenced
+ * @param search_flag A flag specifying the type of subscriber-terminal
+ * instance to be retrieved
+ *
+ * @returns sub_term_inst_t* A pointer to the found subscriber-terminal instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+sub_term_inst *sub_term_inst_get(bcmbal_subscriber_terminal_key *key,
+ sub_term_flag search_flag)
+{
+ sub_term_inst *current_entry = NULL;
+ sub_term_inst *p_temp_entry;
+
+ /*
+ * First, check the active list
+ */
+ TAILQ_FOREACH(current_entry,
+ &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list,
+ sub_term_inst_next)
+ {
+ if((current_entry->api_req_sub_term_info.key.sub_term_id == key->sub_term_id) &&
+ (current_entry->api_req_sub_term_info.key.intf_id == key->intf_id))
+ {
+ /* The sub_term instance pointer is in current_entry */
+ break;
+ }
+ }
+
+
+ if((SUB_TERM_FLAG_ANY == search_flag) && (NULL == current_entry))
+ {
+ /* Now check the free list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list,
+ sub_term_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the free list */
+ TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list,
+ current_entry, sub_term_inst_next);
+
+ /* And add it to the active list */
+ TAILQ_INSERT_TAIL(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list,
+ current_entry, sub_term_inst_next);
+
+ /*
+ * Initialize the sub_term data
+ */
+ current_entry->fsm_state = SUB_TERM_FSM_STATE_NULL;
+
+ break;
+ }
+ }
+
+ if(NULL == current_entry)
+ {
+ /*
+ * A sub_term was not found on either list*/
+
+ BCM_LOG(DEBUG, log_id_sub_term, "no sub_term found\n");
+ }
+
+ return current_entry;
+}
+
+bcmos_errno sub_term_svc_port_id_get(bcmbal_sub_id sub_term_id,
+ uint16_t access_int_id,
+ bcmbal_service_port_id *p_svc_port_id)
+{
+ sub_term_inst *p_sub_term_inst;
+ bcmbal_subscriber_terminal_key sub_term_key;
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BUG_ON(NULL == p_svc_port_id);
+
+ /* Create the key to find the subscriber terminal instance being referenced */
+ sub_term_key.sub_term_id = sub_term_id;
+ sub_term_key.intf_id = access_int_id;
+
+ if(NULL == (p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE)))
+ {
+ BCM_LOG(ERROR, log_id_sub_term, "Specified sub_term (sub:%d on int:%d) not found\n",
+ sub_term_id, access_int_id);
+ ret = BCM_ERR_NOENT;
+ }
+ else
+ {
+ *p_svc_port_id = p_sub_term_inst->current_sub_term_info.data.svc_port_id;
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to free a subscriber terminal instance specified
+ * by a the supplied entry pointer.
+ *
+ * @param p_entry A pointer to the entry to be freed
+ *
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno sub_term_free_by_entry(sub_term_inst *p_entry)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ sub_term_inst *current_entry;
+ sub_term_inst *p_temp_entry;
+
+ BUG_ON(NULL == p_entry);
+
+ /*
+ * First, check the active list (an active sub_term can be in the adding or removing state)
+ */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list,
+ sub_term_inst_next,
+ p_temp_entry)
+ {
+ if(current_entry == p_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list,
+ current_entry, sub_term_inst_next);
+ }
+ }
+
+ /* Initialize the svc_port_id and agg_port_id lists */
+ p_entry->num_svc_port_ids = 0;
+ TAILQ_INIT(&p_entry->svc_port_id_list);
+
+ p_entry->num_agg_port_ids = 0;
+ TAILQ_INIT(&p_entry->agg_port_id_list);
+
+ /* And add the entry to the free list */
+ p_entry->fsm_state = SUB_TERM_FSM_STATE_NULL;
+
+ /* And initialize the current object in the sub_term instance */
+ sub_term_inst_entry_obj_init(p_entry);
+
+ TAILQ_INSERT_TAIL(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list,
+ p_entry, sub_term_inst_next);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_sub_term_svc_port_id_list_entry_add(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id svc_port_id)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ svc_port_id_entry *current_entry;
+
+ do
+ {
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "attempting to add a svc_port_id (%u) entry "
+ "to NULL subscriber terminal\n",
+ svc_port_id);
+
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* Check if the id is already on the list before adding it */
+ TAILQ_FOREACH(current_entry,
+ &p_sub_term_inst->svc_port_id_list,
+ next)
+ {
+ if(current_entry->svc_port_id == svc_port_id)
+ {
+ ret = BCM_ERR_ALREADY;
+ break;
+ }
+ }
+
+ if(BCM_ERR_OK == ret)
+ {
+ /* Get a new entry and configure it */
+ current_entry = bcmos_calloc(sizeof(svc_port_id_entry));
+
+ if (NULL == current_entry)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ current_entry->svc_port_id = svc_port_id;
+
+ /* Save the entry on the list of subscriber-terminal ids on this interface */
+ TAILQ_INSERT_TAIL(&p_sub_term_inst->svc_port_id_list,
+ current_entry, next);
+
+ (p_sub_term_inst->num_svc_port_ids)++;
+ }
+
+ current_entry->ref_count++;
+
+ } while (0);
+
+ return ret;
+
+}
+
+bcmos_errno bcmbal_sub_term_svc_port_id_list_entry_remove(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id svc_port_id)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ svc_port_id_entry *current_entry, *p_temp_entry;
+
+ do
+ {
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "attempting to remove a svc_port_id (%u) entry "
+ "from a NULL subscriber terminal\n",
+ svc_port_id);
+
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &p_sub_term_inst->svc_port_id_list,
+ next,
+ p_temp_entry)
+ {
+ if(current_entry->svc_port_id == svc_port_id)
+ {
+ if(0 == --current_entry->ref_count)
+ {
+ /* Remove it from the list of agg_port_ids on this subscriber terminal */
+ TAILQ_REMOVE(&p_sub_term_inst->svc_port_id_list,
+ current_entry, next);
+
+ bcmos_free(current_entry);
+
+ (p_sub_term_inst->num_svc_port_ids)--;
+ }
+
+ ret = BCM_ERR_OK;
+ break;
+ }
+ }
+ } while (0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_sub_term_agg_port_id_list_entry_add( sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id agg_port_id)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ agg_port_id_entry *current_entry;
+
+ do
+ {
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "attempting to add a svc_port_id (%u) entry "
+ "to a NULL subscriber terminal\n",
+ agg_port_id);
+
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* Check if the id is already on the list before adding it */
+ TAILQ_FOREACH(current_entry,
+ &p_sub_term_inst->agg_port_id_list,
+ next)
+ {
+ if(current_entry->agg_port_id == agg_port_id)
+ {
+ ret = BCM_ERR_ALREADY;
+ break;
+ }
+ }
+
+ if(BCM_ERR_OK == ret)
+ {
+ /* Get a new entry and configure it */
+ current_entry = bcmos_calloc(sizeof(agg_port_id_entry));
+
+ if (NULL == current_entry)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ current_entry->agg_port_id = agg_port_id;
+
+ /* Save the entry on the list of subscriber-terminal ids on this interface */
+ TAILQ_INSERT_TAIL(&p_sub_term_inst->agg_port_id_list,
+ current_entry, next);
+
+ (p_sub_term_inst->num_agg_port_ids)++;
+ }
+
+ (current_entry->ref_count)++;
+
+ } while (0);
+
+ return ret;
+
+}
+
+bcmos_errno bcmbal_sub_term_agg_port_id_list_entry_remove(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id agg_port_id)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ agg_port_id_entry *current_entry, *p_temp_entry;
+
+ do
+ {
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "attempting to remove a agg_port_id (%u) entry "
+ "from a NULL subscriber terminal\n",
+ agg_port_id);
+
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &p_sub_term_inst->agg_port_id_list,
+ next,
+ p_temp_entry)
+ {
+ if(current_entry->agg_port_id == agg_port_id)
+ {
+ if(0 == --current_entry->ref_count)
+ {
+ /* Remove it from the list of agg_port_ids on this subscriber terminal */
+ TAILQ_REMOVE(&p_sub_term_inst->agg_port_id_list,
+ current_entry, next);
+
+ bcmos_free(current_entry);
+
+ (p_sub_term_inst->num_agg_port_ids)--;
+ }
+
+ ret = BCM_ERR_OK;
+ break;
+ }
+ }
+ } while (0);
+
+ return ret;
+}
+
+static bcmos_errno svc_port_id_list_fill(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id_list_u8 *svc_port_id_list)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ svc_port_id_entry *current_entry = NULL;
+ int ii = 0;
+
+ do
+ {
+ /* Traverse the list of svc_port_ids recorded and fill in the list to be returned */
+ svc_port_id_list->len = p_sub_term_inst->num_svc_port_ids;
+ svc_port_id_list->val = bcmos_calloc(sizeof(bcmbal_service_port_id) * svc_port_id_list->len);
+
+ if (NULL == svc_port_id_list->val)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ TAILQ_FOREACH(current_entry,
+ &p_sub_term_inst->svc_port_id_list,
+ next)
+ {
+ svc_port_id_list->val[ii++] = current_entry->svc_port_id;
+ }
+
+ } while (0);
+
+ return ret;
+}
+
+static bcmos_errno agg_port_id_list_fill(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id_list_u8 *agg_port_id_list)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ agg_port_id_entry *current_entry = NULL;
+ int ii = 0;
+
+ do
+ {
+ /* Traverse the list of svc_port_ids recorded and fill in the list to be returned */
+ agg_port_id_list->len = p_sub_term_inst->num_agg_port_ids;
+ agg_port_id_list->val = bcmos_calloc(sizeof(bcmbal_aggregation_port_id) * agg_port_id_list->len);
+
+ if (NULL == agg_port_id_list->val)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ TAILQ_FOREACH(current_entry,
+ &p_sub_term_inst->agg_port_id_list,
+ next)
+ {
+ agg_port_id_list->val[ii++] = current_entry->agg_port_id;
+ }
+
+ } while (0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_sub_term_check_svc_port_in_use(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id svc_port_id)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ svc_port_id_entry *current_entry = NULL;
+
+ do
+ {
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "NULL subscriber terminal\n");
+
+ break;
+ }
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH(current_entry,
+ &p_sub_term_inst->svc_port_id_list,
+ next)
+ {
+ if(current_entry->svc_port_id == svc_port_id)
+ {
+ ret = BCM_ERR_OK;
+ break;
+ }
+ }
+ } while (0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_sub_term_check_agg_port_in_use(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id agg_port_id)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ agg_port_id_entry *current_entry = NULL;
+
+ do
+ {
+ if(NULL == p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "NULL subscriber terminal\n");
+
+ break;
+ }
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH(current_entry,
+ &p_sub_term_inst->agg_port_id_list,
+ next)
+ {
+ if(current_entry->agg_port_id == agg_port_id)
+ {
+ ret = BCM_ERR_OK;
+ break;
+ }
+ }
+ } while (0);
+
+ return ret;
+}
+
+
+
+static bcmos_errno bcmbal_sub_term_tm_scheds_set(const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_key tm_sched_key;
+
+ do
+ {
+ if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg, subscriber_terminal, us_tm))
+ {
+ tm_sched_key.dir = BCMBAL_TM_SCHED_DIR_US;
+ tm_sched_key.id = p_sub_term_cfg->data.us_tm;
+ if(BCM_ERR_OK!= (ret = bcmbal_tm_sched_set_sub_term_owner(tm_sched_key, p_sub_term_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "failed to set sub term us_tm, ret = %s", bcmos_strerror(ret));
+ break;
+ }
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg, subscriber_terminal, ds_tm))
+ {
+ tm_sched_key.dir = BCMBAL_TM_SCHED_DIR_DS;
+ tm_sched_key.id = p_sub_term_cfg->data.ds_tm;
+
+ if(BCM_ERR_OK!= (ret = bcmbal_tm_sched_set_sub_term_owner(tm_sched_key, p_sub_term_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_sub_term,
+ "failed to set sub term ds_tm, ret = %s", bcmos_strerror(ret));
+ break;
+ }
+ }
+ }while(0);
+ return ret;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/main/sub_term_fsm.h b/bal_release/src/core/main/sub_term_fsm.h
new file mode 100755
index 0000000..3d7cf72
--- /dev/null
+++ b/bal_release/src/core/main/sub_term_fsm.h
@@ -0,0 +1,182 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file sub_term_fsm.h
+ * @brief Code to support the BAL Subscriber Terminal FSM
+ *
+ * @defgroup sub_terminal Subscriber Terminal
+ * @ingroup core
+ */
+
+
+#ifndef SUB_TERM_FSM_H
+#define SUB_TERM_FSM_H
+
+/*@{*/
+
+#include <bal_api.h>
+
+/* The current implementation supports a global pool of
+ * ONU instances.
+ */
+#define NUM_SUPPORTED_SUB_TERMS (4096)
+
+typedef enum
+{
+ SUB_TERM_FSM_EVENT_TYPE_NONE = -1,
+ SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP ,
+ SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN ,
+ SUB_TERM_FSM_EVENT_TYPE_REMOVE ,
+ SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG ,
+ SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG ,
+
+
+ SUB_TERM_FSM_EVENT_TYPE__LAST,
+ SUB_TERM_FSM_EVENT_TYPE__NUM_OF
+} sub_term_fsm_event_type;
+
+
+
+typedef enum
+{
+ SUB_TERM_FSM_STATE_NONE = -1,
+ SUB_TERM_FSM_STATE_NULL ,
+ SUB_TERM_FSM_STATE_CONFIGURING ,
+ SUB_TERM_FSM_STATE_CONFIGURED ,
+ SUB_TERM_FSM_STATE_REMOVING ,
+
+
+ SUB_TERM_FSM_STATE__LAST,
+ SUB_TERM_FSM_STATE__NUM_OF
+} sub_term_fsm_state;
+
+
+typedef enum
+{
+ SUB_TERM_FLAG_ANY = 1, /**< ONLY USED in the sub_term get argument */
+ SUB_TERM_FLAG_ACTIVE , /**< A sub_term is on the active list */
+ SUB_TERM_FLAG_FREE /**< A sub_term is on the free list */
+} sub_term_flag;
+
+
+typedef struct sub_term_fsm_event
+{
+ sub_term_fsm_event_type event_type; /**< The sub_term FSM event */
+ void *msg;
+} sub_term_fsm_event;
+
+
+typedef struct svc_port_id_entry
+{
+ bcmbal_service_port_id svc_port_id;
+ uint8_t ref_count; /**< A count of the number of re-uses of this svc_port_id on this subscriber terminal */
+ TAILQ_ENTRY(svc_port_id_entry) next ; /**< TAILQ link */
+}svc_port_id_entry;
+
+typedef struct agg_port_id_entry
+{
+ bcmbal_aggregation_port_id agg_port_id;
+ uint8_t ref_count; /**< A count of the number of re-uses of this agg_port_id on this subscriber terminal */
+ TAILQ_ENTRY(agg_port_id_entry) next ; /**< TAILQ link */
+}agg_port_id_entry;
+
+typedef struct sub_term_inst sub_term_inst;
+struct sub_term_inst
+{
+ bcmbal_subscriber_terminal_cfg current_sub_term_info; /**< The current information for this sub_term (used for GET) */
+ bcmbal_subscriber_terminal_cfg api_req_sub_term_info; /**< The last sub_term object info received from the Public API */
+ sub_term_fsm_state fsm_state; /**< The sub_term instance FSM state */
+ uint16_t num_svc_port_ids; /**< The number of bearer traffic GEMs on this subscriber terminal */
+ TAILQ_HEAD(svc_port_id_list_head, svc_port_id_entry) svc_port_id_list; /* A list of svc_port_ids on this subscriber terminal */
+ uint16_t num_agg_port_ids; /**< The number of alloc ids on this subscriber terminal */
+ TAILQ_HEAD(agg_port_id_list_head, agg_port_id_entry) agg_port_id_list; /* A list of svc_port_ids on this subscriber terminal */
+ TAILQ_ENTRY(sub_term_inst) sub_term_inst_next ; /**< TAILQ link for active list and free list management */
+};
+
+
+/*
+ * Sub_Term FSM data structures
+ */
+typedef struct sub_term_fsm_ctx
+{
+ /* Lists of free sub_term entries and active sub_term entries
+ */
+ TAILQ_HEAD(free_sub_term_list_head, sub_term_inst) free_sub_term_list;
+
+ TAILQ_HEAD(active_sub_term_list_head, sub_term_inst) active_sub_term_list;
+
+} sub_term_fsm_ctx;
+
+
+/*
+ * Function declarations
+ */
+extern bcmos_errno sub_term_fsm_init(void);
+
+extern bcmos_errno sub_term_fsm_finish(void);
+
+extern bcmos_errno process_subscriber_terminal_object(void *msg_payload);
+
+extern bcmos_errno process_subscriber_terminal_util_msg(void *msg_payload);
+
+extern sub_term_inst *sub_term_inst_get(bcmbal_subscriber_terminal_key *key,
+ sub_term_flag sub_term_flag);
+
+extern bcmos_errno sub_term_svc_port_id_get(bcmbal_sub_id sub_term_id,
+ uint16_t access_int_id,
+ bcmbal_service_port_id *p_svc_port_id);
+
+extern bcmos_errno bcmbal_sub_term_svc_port_id_list_entry_add(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id svc_port_id);
+
+extern bcmos_errno bcmbal_sub_term_svc_port_id_list_entry_remove(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id svc_port_id);
+
+bcmos_errno bcmbal_sub_term_agg_port_id_list_entry_add(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id agg_port_id);
+
+bcmos_errno bcmbal_sub_term_agg_port_id_list_entry_remove(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id agg_port_id);
+
+bcmos_errno bcmbal_sub_term_check_agg_port_in_use(sub_term_inst *p_sub_term_inst,
+ bcmbal_aggregation_port_id agg_port_id);
+
+bcmos_errno bcmbal_sub_term_check_svc_port_in_use(sub_term_inst *p_sub_term_inst,
+ bcmbal_service_port_id svc_port_id);
+
+
+
+/*@}*/
+
+#endif /*SUB_TERM_FSM_H */
+
+
diff --git a/bal_release/src/core/main/tm_queue_fsm.c b/bal_release/src/core/main/tm_queue_fsm.c
new file mode 100755
index 0000000..a9999cb
--- /dev/null
+++ b/bal_release/src/core/main/tm_queue_fsm.c
@@ -0,0 +1,981 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file tm_queue_fsm.c
+ * @brief Code to support the BAL tm_queue FSM
+ *
+ *
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <tm_queue_fsm.h>
+#include <bal_msg.h>
+#include <bal_osmsg.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include "rsc_mgr.h"
+
+#include <bal_objs.h>
+#include <fsm_common.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+ /*
+ * @brief The logging device id for tm queue
+ */
+static dev_log_id log_id_tm_queue;
+#endif
+
+/* local function declarations */
+
+static bcmos_errno tm_queue_free_by_entry(tm_queue_inst *p_entry);
+static bcmos_errno tm_queue_fsm_state_err(tm_queue_inst *p_tm_queue_inst, void *msg, tm_queue_fsm_event *p_event);
+static void tm_queue_inst_entry_obj_init(tm_queue_inst *p_entry);
+
+/*
+ * @brief The Global tm_queue fsm context data structure
+ */
+static tm_queue_fsm_ctx g_tm_queue_fsm_tm_queue_list_ctx;
+
+/*
+ * Macros for tm_queue ctx access
+ */
+#define TM_QUEUE_FSM_TM_QUEUE_LIST_CTX (g_tm_queue_fsm_tm_queue_list_ctx)
+#define TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR (&g_tm_queue_fsm_tm_queue_list_ctx)
+
+
+/*
+ * @brief The definition of a tm_queue FSM state processing function
+ */
+typedef bcmos_errno (* tm_queue_fsm_state_processor)(tm_queue_inst *, void *, tm_queue_fsm_event *);
+static bcmos_errno bcmbal_tm_queue_create(tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event);
+
+static bcmos_errno bcmbal_tm_queue_active_destroy (tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event);
+static bcmos_errno bcmbal_tm_queue_inactive_destroy(tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event);
+
+
+static tm_queue_fsm_state_processor tm_queue_states[TM_QUEUE_FSM_STATE__NUM_OF][TM_QUEUE_FSM_EVENT_TYPE__NUM_OF] =
+{
+ [TM_QUEUE_FSM_STATE_NULL] =
+ {
+ [TM_QUEUE_FSM_EVENT_TYPE_CREATE] = bcmbal_tm_queue_create,
+ },
+ [TM_QUEUE_FSM_STATE_INACTIVE] =
+ {
+ [TM_QUEUE_FSM_EVENT_TYPE_DESTROY] = bcmbal_tm_queue_inactive_destroy,
+ },
+ [TM_QUEUE_FSM_STATE_ACTIVE] =
+ {
+ [TM_QUEUE_FSM_EVENT_TYPE_DESTROY] = bcmbal_tm_queue_active_destroy,
+ },
+
+};
+
+static char *state_name_str[] =
+{
+ "TM_QUEUE_FSM_STATE_NULL",
+ "TM_QUEUE_FSM_STATE_INACTIVE",
+ "TM_QUEUE_FSM_STATE_ACTIVE",
+ "TM_QUEUE_FSM_STATE_IN_USE",
+ "TM_QUEUE_FSM_STATE_DELETING",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT(TM_QUEUE_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), tm_queue_fsm_state);
+
+static char *tm_queue_state_name_get(tm_queue_fsm_state state)
+{
+ if(state < TM_QUEUE_FSM_STATE__LAST)
+ {
+ return state_name_str[state];
+ }
+ else
+ {
+ return "TM_QUEUE_UNKNOWN";
+ }
+}
+
+static char *event_name_str[] =
+{
+ "TM_QUEUE_FSM_CREATE_EVENT",
+ "TM_QUEUE_FSM_DESTROY_EVENT",
+ "FLOW_FSM_UTIL_MSG_EVENT",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT(TM_QUEUE_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), tm_queue_fsm_event_type);
+
+static char *tm_queue_event_name_get(tm_queue_fsm_event_type event)
+{
+ if(event < TM_QUEUE_FSM_EVENT_TYPE__LAST)
+ {
+ return event_name_str[event];
+ }
+ else
+ {
+ return "TM_QUEUE_EVT_UNKNOWN";
+ }
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Tm queue FSM function which is executed when an error
+ * is encountered during FSM processing.
+ *
+ * @param p_tm_queue_inst Pointer to a tm_queue instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to a tm_queue event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_queue_fsm_state_err(tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_INVALID_OP;
+
+ BCM_LOG(DEBUG, log_id_tm_queue,
+ "Error encountered processing TM_queue FSM"
+ " - BAD EVENT ()\n");
+
+ return ret;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the Tm Queue FSM infrastructure.
+ *
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno tm_queue_fsm_init(void)
+{
+ int ii;
+ tm_queue_inst *new_entry;
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifdef ENABLE_LOG
+ log_id_tm_queue = bcm_dev_log_id_register("TM_QUEUE", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_tm_queue == DEV_LOG_INVALID_ID);
+#endif
+
+ /* Initialize all of the tm_queue queues */
+ TAILQ_INIT(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list);
+ TAILQ_INIT(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list);
+
+ /* Populate the free list with it's initial set of tm_queues
+ */
+ for(ii=0; ii<TM_QUEUE_ALLOCATION_BLOCK_SIZE; ii++)
+ {
+ new_entry = bcmos_calloc(sizeof(tm_queue_inst));
+ if(NULL == new_entry)
+ {
+ BCM_LOG(FATAL, log_id_tm_queue, "Failed to initialize the tm_queue free list - FATAL\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+ tm_queue_free_by_entry(new_entry);
+ }
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to un-initialize the Tm Queue FSM infrastructure.
+ *
+ * NOTE: This is called once on shutdown and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno tm_queue_fsm_finish(void)
+{
+
+ tm_queue_inst *current_entry, *p_temp_entry;
+
+ /* Free all the entries on the active list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list,
+ tm_queue_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list, current_entry, tm_queue_inst_next);
+
+ bcmos_free(current_entry);
+
+ }
+
+ /* Free all the entries on the free list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list,
+ tm_queue_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list, current_entry, tm_queue_inst_next);
+
+ bcmos_free(current_entry);
+ }
+
+ return BCM_ERR_OK;
+}
+
+static void tm_queue_inst_entry_obj_init(tm_queue_inst *p_entry)
+{
+ /* The actual key content is irrelevant for free tm_queues */
+ bcmbal_tm_queue_key key = { .id = 0, .sched_id = 0, .sched_dir = BCMBAL_TM_SCHED_DIR_US};
+
+ /* And add it to the free list */
+ p_entry->fsm_state = TM_QUEUE_FSM_STATE_NULL;
+
+ BCMBAL_CFG_INIT(&p_entry->current_tm_queue_info,
+ tm_queue,
+ key);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_tm_queue_info), BCMOS_FALSE);
+}
+/*****************************************************************************/
+/**
+ * @brief A function to free a tm_queue instance specified by a the supplied
+ * entry pointer.
+ *
+ * @param p_entry A pointer to the entry to be freed
+ *
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_queue_free_by_entry(tm_queue_inst *p_entry)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_queue_inst *current_entry;
+ tm_queue_inst *p_temp_entry;
+
+ /*
+ * First, check the active list (an active tm_queue can be in the adding or removing state)
+ */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list,
+ tm_queue_inst_next,
+ p_temp_entry)
+ {
+ if(current_entry == p_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list, current_entry, tm_queue_inst_next);
+ break;
+ }
+ }
+ tm_queue_inst_entry_obj_init(p_entry);
+ TAILQ_INSERT_TAIL(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list, p_entry, tm_queue_inst_next);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The Tm queue FSM state processing executive function
+ * @param p_tm_queue_inst Pointer to a tm_queu instance
+ * @param p_event Pointer to a tm_Queue event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_queue_fsm_exec(tm_queue_inst *p_tm_queue_inst, tm_queue_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_queue_fsm_state pre_state;
+ tm_queue_fsm_state_processor tm_queue_state_processor;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_tm_queue_inst);
+ BUG_ON(NULL == p_event);
+
+ /* Record the present state for debug printing
+ */
+ pre_state = p_tm_queue_inst->fsm_state;
+
+ /*
+ * Get the state processing function
+ */
+ tm_queue_state_processor = tm_queue_states[p_tm_queue_inst->fsm_state][p_event->event_type];
+
+ /*
+ * If there's a state processing function for this event and state, execute it.
+ * Otherwise, process a generic error.
+ */
+ if(tm_queue_state_processor)
+ {
+ ret = tm_queue_state_processor(p_tm_queue_inst, p_event->msg, p_event);
+ }
+ else
+ {
+ tm_queue_fsm_state_err(p_tm_queue_inst, p_event->msg, p_event);
+ }
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "*** Error detected during state processing\n");
+ p_tm_queue_inst->fsm_state = pre_state;
+ }
+
+ BCM_LOG(DEBUG, log_id_tm_queue, "*** Event %s, State: %s --> %s\n\n",
+ tm_queue_event_name_get(p_event->event_type),
+ tm_queue_state_name_get(pre_state),
+ tm_queue_state_name_get(p_tm_queue_inst->fsm_state));
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a tm_queue instance of the specified class.
+ *
+ * @param key A pointer to the key of the tm_queue being referenced
+ * @param search_flag A flag specifying the type of tm_queue
+ * instance to be retrieved
+ *
+ * @returns tm_queue_inst_t* A pointer to the found tm_queue instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+tm_queue_inst *tm_queue_inst_get(bcmbal_tm_queue_key key, tm_queue_flag search_flag)
+{
+ tm_queue_inst *current_entry = NULL;
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ if(TM_QUEUE_FLAG_ACTIVE & search_flag)
+ {
+ TAILQ_FOREACH(current_entry,
+ &TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list,
+ tm_queue_inst_next)
+ {
+
+ if(current_entry->api_req_tm_queue_info.key.id == key.id
+ && current_entry->api_req_tm_queue_info.key.sched_id == key.sched_id
+ && current_entry->api_req_tm_queue_info.key.sched_dir == key.sched_dir)
+ {
+ BCM_LOG(DEBUG, log_id_tm_queue, "Found active tm_queue\n");
+ /* The tm_queue instance pointer is in current_entry */
+ break;
+ }
+ }
+ }
+ /*
+ * Next, check the free list if the caller has chosen to do so
+ */
+ if((TM_QUEUE_FLAG_FREE & search_flag) && (NULL == current_entry))
+ {
+ /* Now check the free list */
+ if(!TAILQ_EMPTY(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list))
+ {
+ /* Just grab the first entry */
+ current_entry = TAILQ_FIRST(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list);
+
+ /* Remove it from the free list */
+ TAILQ_REMOVE(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->free_tm_queue_list, current_entry, tm_queue_inst_next);
+
+ /* And add it to the active list */
+ TAILQ_INSERT_TAIL(&TM_QUEUE_FSM_TM_QUEUE_LIST_CTX_PTR->active_tm_queue_list, current_entry, tm_queue_inst_next);
+
+ /*
+ * Initialize the fsm state
+ */
+ current_entry->fsm_state = TM_QUEUE_FSM_STATE_NULL;
+
+ BCM_LOG(DEBUG, log_id_tm_queue, "Using new tm_queue\n");
+ }
+ }
+
+ if((TM_QUEUE_FLAG_ANY & search_flag) && (NULL == current_entry))
+ {
+ /*A tm_queue was not found on either list*/
+
+ BCM_LOG(DEBUG, log_id_tm_queue, "************** ERROR: no tm_queue found\n");
+ }
+
+ return current_entry;
+}
+
+static bcmos_errno bcmbal_tm_queue_validate(bcmbal_tm_queue_cfg *p_tm_queue_cfg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_key tm_sched_key = {.id = p_tm_queue_cfg->key.sched_id, .dir = p_tm_queue_cfg->key.sched_dir};
+ tm_sched_inst *p_tm_sched_inst = NULL;
+ do
+ {
+ /*get the tm sched instance*/
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR: no related tm_sched found (id = %d dir = %s)\n",
+ tm_sched_key.id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir));
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ /*check it is not an agg port tm sched - as there are no queues to such node*/
+ if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
+ {
+ if(BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT == p_tm_sched_inst->req_tm_sched_info.data.owner.type)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR: should not attach queue to node which is owned by agg port (id = %d dir = %s)\n",
+ tm_sched_key.id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir));
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+
+ /*sched level should be 'queue'*/
+ if(BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE != p_tm_sched_inst->req_tm_sched_info.data.sched_child_type)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR: tm sched sched level is invalid (%d), should be BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE\n",
+ p_tm_sched_inst->req_tm_sched_info.data.sched_child_type);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /*based on sched type, check priority / weight is set and is valid */
+ if(BCMBAL_TM_SCHED_TYPE_SP == p_tm_sched_inst->req_tm_sched_info.data.sched_type)
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, priority))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue must be set with a priority, as its scheduler' sched_type is sp\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue can not be set with a weight, as its scheduler' sched_type is sp\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(p_tm_queue_cfg->data.priority >= p_tm_sched_inst->req_tm_sched_info.data.num_priorities)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue priority (%d) is higher than the allowed at parent scheduler (id = %d dir = %s num of priorities = %d )\n",
+ p_tm_queue_cfg->data.priority , tm_sched_key.id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir),
+ p_tm_sched_inst->req_tm_sched_info.data.num_priorities);
+
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ if(BCMBAL_TM_SCHED_TYPE_WFQ == p_tm_sched_inst->req_tm_sched_info.data.sched_type)
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue must be set with a weight, as its scheduler' sched_type sched_type is wfq\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, priority))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue can not be set with a priority, as its scheduler' sched_type sched_type is wfq \n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ if(BCMBAL_TM_SCHED_TYPE_SP_WFQ == p_tm_sched_inst->req_tm_sched_info.data.sched_type)
+ {
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, priority)
+ && BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue must be set with either weight or priority, not both. as its scheduler' sched_type is sp_wfq\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(!BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, priority)
+ && !BCMBAL_CFG_PROP_IS_SET(p_tm_queue_cfg, tm_queue, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Queue must be set with either weight or priority, as its scheduler' sched_type is sp_wfq\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ }while(0);
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function called by the core worker thread to process an
+ * tm_queue object message (SET, GET, CLEAR, STATS) received
+ * from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_tm_queue_object(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_queue_cfg *p_tm_queue_cfg = (bcmbal_tm_queue_cfg *)msg_payload;
+ tm_queue_inst *p_tm_queue_inst = NULL;
+ tm_queue_fsm_event fsm_event;
+ bcmbal_tm_queue_key tm_queue_key;
+ bcmbal_obj_msg_type oper_type;
+ bcmbal_tm_sched_key tm_sched_key;
+ tm_sched_inst *p_tm_sched_inst = NULL;
+ bcmbal_interface_key intf_key;
+ bcmbal_tm_sched_owner owner;
+
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id_tm_queue, "Processing a tm queue object\n");
+
+ tm_queue_key = p_tm_queue_cfg->key;
+ oper_type = p_tm_queue_cfg->hdr.hdr.type;
+
+ /*
+ * A message pointer may be passed inside the event structure.
+ */
+ fsm_event.msg = msg_payload;
+
+ /* SET or GET or CLEAR...? */
+ switch(oper_type)
+ {
+ case(BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+ do
+ {
+ BCM_LOG(DEBUG, log_id_tm_queue, "Processing a tm queue SET REQ mgmt message\n");
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ /*Find the specified tm_queue instance is already created */
+ p_tm_queue_inst = tm_queue_inst_get(tm_queue_key, TM_QUEUE_FLAG_ACTIVE);
+
+ if(NULL != p_tm_queue_inst)
+ {
+ /* This is a fatal error condition */
+ BCM_LOG(ERROR, log_id_tm_queue,
+ "ERROR - tm queue found. Set after create is currently not supported. No further processing\n");
+ ret = BCM_ERR_NOT_SUPPORTED;
+ break;
+ }
+
+ p_tm_queue_inst = tm_queue_inst_get(tm_queue_key, TM_QUEUE_FLAG_FREE);
+ if(NULL == p_tm_queue_inst )
+ {
+ /* This is a fatal error condition */
+ BCM_LOG(ERROR, log_id_tm_queue,
+ "ERROR - tm queue not found. No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+ if(BCM_ERR_OK != (ret = bcmbal_tm_queue_validate(p_tm_queue_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "tm_queue fsm validation Failed (%d)\n", ret);
+ tm_queue_free_by_entry(p_tm_queue_inst);
+ break;
+ }
+
+
+ /* Perform the validation check(s) that the utils require */
+ if(BCM_ERR_OK != (ret = sw_util_tm_queue_validate(p_tm_queue_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "tm_queue switch validation Failed (%d)\n", ret);
+ tm_queue_free_by_entry(p_tm_queue_inst);
+ break;
+ }
+
+
+
+ BCM_LOG(DEBUG, log_id_tm_queue,
+ "Creating a new tm queue\n");
+
+ }while(0);
+
+ ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_queue);
+
+ if(BCM_ERR_OK != ret )
+ {
+ break;
+ }
+
+ BCMBAL_CFG_PROP_SET(p_tm_queue_cfg, tm_queue, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
+
+ bcmbal_tm_queue_object_overlay(&p_tm_queue_inst->api_req_tm_queue_info, p_tm_queue_cfg);
+
+ fsm_event.event_type = TM_QUEUE_FSM_EVENT_TYPE_CREATE;
+ fsm_event.msg = msg_payload;
+ ret = tm_queue_fsm_exec(p_tm_queue_inst,&fsm_event);
+ }
+ break;
+
+ case(BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+ BCM_LOG(DEBUG, log_id_tm_queue, "Processing a tm queue GET REQ mgmt message\n");
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ }
+ else
+ {
+ /* Find the specified tm_queue instance */
+ p_tm_queue_inst = tm_queue_inst_get(tm_queue_key, TM_QUEUE_FLAG_ACTIVE);
+ }
+
+ if(NULL == p_tm_queue_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR - Specified tm_queue (%d) not found\n", tm_queue_key.id);
+ ret = BCM_ERR_NOENT;
+
+ }
+ else
+ {
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested */
+ p_tm_queue_inst->api_req_tm_queue_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+ *((bcmbal_tm_queue_cfg *)msg_payload) = p_tm_queue_inst->api_req_tm_queue_info;
+ }
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_queue);
+ }
+ break;
+
+ case(BCMBAL_OBJ_MSG_TYPE_CLEAR):
+ {
+ do
+ {
+ BCM_LOG(DEBUG, log_id_tm_queue, "Processing a tm queue CLEAR REQ mgmt message\n");
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+ /*
+ * Find the specified tm_queue instance
+ */
+ p_tm_queue_inst = tm_queue_inst_get(tm_queue_key, TM_QUEUE_FLAG_ACTIVE);
+
+ if(NULL == p_tm_queue_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Specified tm_queue not found on CLEAR\n");
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+
+ if(TM_QUEUE_FSM_STATE_IN_USE == p_tm_queue_inst->fsm_state)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Specified tm_queue is in use and can not be removed\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /*TM_QUEUEs (either auto or manually created) that are associated with a TM_NODE with owner interface
+ may only be deleted when the associated interface is in the ADMIN-DOWN state*/
+ tm_sched_key.id = tm_queue_key.sched_id;
+ tm_sched_key.dir = tm_queue_key.sched_dir;
+
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "ERROR: no related tm_sched found (id = %d dir = %s)\n",
+ tm_sched_key.id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir));
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(&(p_tm_sched_inst->req_tm_sched_info), tm_sched, owner))
+ {
+ owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+ switch(owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ intf_key.intf_type = owner.u.interface.intf_type;
+ intf_key.intf_id = owner.u.interface.intf_id;
+ if(BCMBAL_STATUS_DOWN != bcmbal_interface_status_get(intf_key))
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Specified tm_queue is attached to sched that is owned by interface that is not admin down, and can be removed only when the associated interface is in the ADMIN-DOWN state\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ /*generate destroy event*/
+
+ fsm_event.event_type = TM_QUEUE_FSM_EVENT_TYPE_DESTROY;
+ fsm_event.msg = msg_payload;
+ ret = tm_queue_fsm_exec(p_tm_queue_inst,&fsm_event);
+
+ }while(0);
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_queue);
+ }
+ break;
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "Unsupported operation on tm queue object (%d)\n", oper_type );
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_queue);
+ }
+ }
+
+ BCM_LOG(DEBUG, log_id_tm_queue, "%s returns\n", __FUNCTION__);
+ return ret;
+
+}
+
+bcmos_errno bcmbal_tm_queue_auto_create(bcmbal_tm_queue_cfg cfg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_queue_inst *p_tm_queue_inst = NULL;
+ do
+ {
+ /*Find a free tm_queue instance */
+ p_tm_queue_inst = tm_queue_inst_get(cfg.key, TM_QUEUE_FLAG_FREE);
+ if(NULL == p_tm_queue_inst)
+ {
+ /* This is a fatal error condition*/
+ BCM_LOG(ERROR, log_id_tm_queue,"ERROR - tm queue not found. No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+ p_tm_queue_inst->api_req_tm_queue_info = cfg;
+ ret = bcmbal_tm_queue_create(p_tm_queue_inst,NULL, NULL);
+ }while(0);
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_queue_activate(tm_queue_inst *p_tm_queue_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+
+ ret = sw_util_tm_queue_set(p_tm_queue_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "queue could not be set by switch\n");
+ break;
+ }
+
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_ACTIVE;
+ /* The hardware has properly accepted the object info, so the request object becomes
+ * the current state.
+ */
+ bcmbal_tm_queue_object_overlay(&p_tm_queue_inst->current_tm_queue_info,
+ &p_tm_queue_inst->api_req_tm_queue_info);
+
+ }while(0);
+ return ret;
+
+}
+
+bcmos_errno bcmbal_tm_queue_deactivate(tm_queue_inst *p_tm_queue_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BUG_ON(NULL == p_tm_queue_inst);
+
+ do
+ {
+ ret = sw_util_tm_queue_clear(p_tm_queue_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "queue could not be set by switch\n");
+ break;
+ }
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_INACTIVE;
+ }while(0);
+ return ret;
+
+}
+static bcmos_errno bcmbal_tm_queue_create(tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_INACTIVE;
+
+ /*referenced tm sched exist for sure as it was already validated*/
+ ret = bcmbal_tm_sched_set_queue(p_tm_queue_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "queue could not be attched to node \n");
+ break;
+ }
+ }while(0);
+ return ret;
+
+}
+
+bcmos_errno bcmbal_tm_queue_set_owner(bcmbal_tm_queue_key key)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_queue_inst *p_tm_queue_inst;
+ do
+ {
+ p_tm_queue_inst = tm_queue_inst_get(key,TM_QUEUE_FLAG_ACTIVE);
+ if(NULL == p_tm_queue_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue,"ERROR - tm queue not found. No further processing\n");
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ ret = bcmbal_tm_queue_activate(p_tm_queue_inst);
+ }while(0);
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_queue_unset_owner(bcmbal_tm_queue_key key)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_queue_inst *p_tm_queue_inst;
+ do
+ {
+ p_tm_queue_inst = tm_queue_inst_get(key,TM_QUEUE_FLAG_ACTIVE);
+ if(NULL == p_tm_queue_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue,"ERROR - tm queue not found. No further processing\n");
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ ret = bcmbal_tm_queue_deactivate(p_tm_queue_inst);
+
+ }while(0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_queue_use_set(tm_queue_inst *p_tm_queue_inst, bcmos_bool is_in_use)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BUG_ON(NULL == p_tm_queue_inst);
+ if(is_in_use)
+ {
+ /*queue might already in requested state*/
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_IN_USE;
+ p_tm_queue_inst->api_req_tm_queue_info.data.ref_count++;
+ }
+ else
+ {
+ if(p_tm_queue_inst->api_req_tm_queue_info.data.ref_count)
+ {
+ p_tm_queue_inst->api_req_tm_queue_info.data.ref_count--;
+
+ if(0 == p_tm_queue_inst->api_req_tm_queue_info.data.ref_count)
+ {
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_ACTIVE;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "queue (sched.id = %d sched.dir = %s queue.id = %d) could not be unset as no flows assign to it \n", p_tm_queue_inst->api_req_tm_queue_info.key.sched_id, TM_SCHED_DIR_TO_STR(p_tm_queue_inst->api_req_tm_queue_info.key.sched_dir), p_tm_queue_inst->api_req_tm_queue_info.key.id);
+ ret = BCM_ERR_INTERNAL;
+ }
+ }
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_queue_destroy(tm_queue_inst *p_tm_queue_inst, bcmos_bool remove_from_node)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_DELETING;
+ if(remove_from_node)
+ {
+ ret = bcmbal_tm_sched_remove_queue(p_tm_queue_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "queue could not be cleaared from its tm sched\n");
+ break;
+ }
+ }
+ ret = tm_queue_free_by_entry(p_tm_queue_inst);
+ }while(0);
+ return ret;
+}
+
+static bcmos_errno bcmbal_tm_queue_inactive_destroy(tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event)
+{
+ return bcmbal_tm_queue_destroy(p_tm_queue_inst, BCMOS_TRUE);
+}
+
+static bcmos_errno bcmbal_tm_queue_active_destroy(tm_queue_inst *p_tm_queue_inst,
+ void *msg,
+ tm_queue_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+ p_tm_queue_inst->fsm_state = TM_QUEUE_FSM_STATE_DELETING;
+ ret = sw_util_tm_queue_clear(p_tm_queue_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_queue, "queue could not be cleaared from the switch\n");
+ break;
+ }
+ ret = bcmbal_tm_queue_inactive_destroy(p_tm_queue_inst, msg, p_event);
+ }while(0);
+ return ret;
+}
+/*@}*/
diff --git a/bal_release/src/core/main/tm_queue_fsm.h b/bal_release/src/core/main/tm_queue_fsm.h
new file mode 100755
index 0000000..1240cf1
--- /dev/null
+++ b/bal_release/src/core/main/tm_queue_fsm.h
@@ -0,0 +1,139 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file tm_queue_fsm.h
+ * @brief Code to support the BAL tm_queue FSM
+ *
+ */
+
+#ifndef TM_QUEUE_FSM_H
+#define TM_QUEUE_FSM_H
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bal_api.h>
+
+/* set the total pool size of available tm queue to 4k */
+#define TM_QUEUE_ALLOCATION_BLOCK_SIZE (4096)
+
+typedef enum
+{
+ TM_QUEUE_FSM_EVENT_TYPE_NONE = -1,
+ TM_QUEUE_FSM_EVENT_TYPE_CREATE ,
+ TM_QUEUE_FSM_EVENT_TYPE_DESTROY ,
+ TM_QUEUE_FSM_EVENT_TYPE_UTIL_MSG ,
+
+ TM_QUEUE_FSM_EVENT_TYPE__LAST,
+ TM_QUEUE_FSM_EVENT_TYPE__NUM_OF
+} tm_queue_fsm_event_type;
+
+
+
+typedef enum
+{
+ TM_QUEUE_FSM_STATE_NONE = -1,
+ TM_QUEUE_FSM_STATE_NULL ,
+ TM_QUEUE_FSM_STATE_INACTIVE ,
+ TM_QUEUE_FSM_STATE_ACTIVE ,
+ TM_QUEUE_FSM_STATE_IN_USE ,
+ TM_QUEUE_FSM_STATE_DELETING ,
+
+ TM_QUEUE_FSM_STATE__LAST,
+ TM_QUEUE_FSM_STATE__NUM_OF
+} tm_queue_fsm_state;
+
+
+typedef enum
+{
+ TM_QUEUE_FLAG_ACTIVE = 1<<0, /**< A tm_queue is on the active list */
+ TM_QUEUE_FLAG_FREE = 1<<1, /**< A tm_queue is on the free list */
+ TM_QUEUE_FLAG_ANY = (TM_QUEUE_FLAG_ACTIVE | TM_QUEUE_FLAG_FREE), /**< A tm_queue is on either the active or free list */
+} tm_queue_flag;
+
+
+typedef struct tm_queue_fsm_event_t
+{
+ tm_queue_fsm_event_type event_type; /**< The tm_queue fsm events */
+ void *msg;
+
+ /* other necessary information */
+} tm_queue_fsm_event;
+
+
+typedef struct tm_queue_inst tm_queue_inst;
+struct tm_queue_inst
+{
+ bcmbal_tm_queue_cfg current_tm_queue_info; /**< The current information for this tm queue (used for GET) */
+ bcmbal_tm_queue_cfg api_req_tm_queue_info; /**< The tm queue object info received from the Public API */
+ tm_queue_fsm_state fsm_state; /**< The tm queue FSM state */
+
+ TAILQ_ENTRY(tm_queue_inst) tm_queue_inst_next; /**< TAILQ link */
+};
+
+
+/*
+ * tm_queue FSM data structures
+ */
+typedef struct tm_queue_fsm_ctx
+{
+ /* Lists of free tm_queue entries and active tm_queue entries
+ */
+ TAILQ_HEAD(free_tm_queue_list_head, tm_queue_inst) free_tm_queue_list;
+
+ TAILQ_HEAD(active_tm_queue_list_head, tm_queue_inst) active_tm_queue_list;
+
+} tm_queue_fsm_ctx;
+
+
+/* Function declarations */
+
+extern bcmos_errno tm_queue_fsm_init(void);
+extern bcmos_errno tm_queue_fsm_finish(void);
+extern bcmos_errno process_tm_queue_object(void *msg_payload);
+
+extern tm_queue_inst *tm_queue_inst_get(bcmbal_tm_queue_key key, tm_queue_flag search_flag);
+extern bcmos_errno bcmbal_tm_queue_auto_create(bcmbal_tm_queue_cfg tm_queue_default_cfg);
+extern bcmos_errno bcmbal_tm_queue_set_owner(bcmbal_tm_queue_key key);
+extern bcmos_errno bcmbal_tm_queue_unset_owner(bcmbal_tm_queue_key key);
+
+extern bcmos_errno bcmbal_tm_queue_activate(tm_queue_inst *p_tm_queue_inst);
+extern bcmos_errno bcmbal_tm_queue_deactivate(tm_queue_inst *p_tm_queue_inst);
+extern bcmos_errno bcmbal_tm_queue_use_set(tm_queue_inst *p_tm_queue_inst, bcmos_bool is_in_use);
+extern bcmos_errno bcmbal_tm_queue_destroy(tm_queue_inst *p_tm_queue_inst, bcmos_bool remove_from_node);
+
+
+
+/*@}*/
+
+#endif /*TM_QUEUE_FSM_H */
+
diff --git a/bal_release/src/core/main/tm_sched_fsm.c b/bal_release/src/core/main/tm_sched_fsm.c
new file mode 100644
index 0000000..50424cb
--- /dev/null
+++ b/bal_release/src/core/main/tm_sched_fsm.c
@@ -0,0 +1,2229 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file tm_sched_fsm.c
+ * @brief Code to support the BAL tm_sched FSM
+ *
+ *
+ */
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <tm_sched_fsm.h>
+#include <bal_msg.h>
+#include <bal_osmsg.h>
+#include "bal_worker.h"
+#include "bal_mac_util.h"
+#include "bal_switch_util.h"
+#include <bal_api.h>
+//#include <bal_mac_util_common_itu_pon.h>
+
+
+#include <bal_objs.h>
+#include <fsm_common.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+ /*
+ * @brief The logging device id for tm sched
+ */
+static dev_log_id log_id_tm_sched;
+#endif
+
+/* local function declarations */
+
+static bcmos_errno tm_sched_fsm_create(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+
+static bcmos_errno tm_sched_free_by_entry(tm_sched_inst *p_entry);
+static void tm_sched_inst_entry_obj_init(tm_sched_inst *p_entry);
+static bcmos_errno queues_list_fill(tm_sched_inst *p_tm_sched_inst,
+ bcmbal_tm_queue_id_list_u8 *queues_list);
+
+
+static bcmos_errno tm_sched_fsm_state_err(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+static bcmos_errno tm_sched_fsm_assigned_process_util_msg(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+static bcmos_errno tm_sched_fsm_deleting_process_util_msg(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+
+static bcmos_errno tm_sched_fsm_inactive_destroy(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+
+static bcmos_errno tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+
+static bcmos_errno tm_sched_fsm_assigned_destroy(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event);
+
+static bcmos_errno tm_sched_fsm_destroy(tm_sched_inst *p_tm_sched_inst);
+
+static bcmos_errno tm_sched_fsm_exec(tm_sched_inst *p_tm_sched_inst, tm_sched_fsm_event *p_event);
+
+static tm_sched_inst* tm_sched_find_by_owner(bcmbal_tm_sched_owner owner);
+
+static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_add(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id);
+static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_remove(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id);
+
+static bcmos_errno sub_scheds_list_fill(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id_list_u8 *sub_scheds_list);
+/*
+ * @brief The Global tm_sched fsm context data structure
+ */
+static tm_sched_fsm_ctx g_tm_sched_fsm_tm_sched_list_ctx;
+
+/*
+ * Macros for tm_sched ctx access
+ */
+#define TM_SCHED_FSM_TM_SCHED_LIST_CTX (g_tm_sched_fsm_tm_sched_list_ctx)
+#define TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR (&g_tm_sched_fsm_tm_sched_list_ctx)
+
+
+/*
+ * @brief The definition of a tm_sched FSM state processing function
+ */
+typedef bcmos_errno (* tm_sched_fsm_state_processor)(tm_sched_inst *, void *, tm_sched_fsm_event *);
+/*
+ * @brief The tm sched FSM state processing array
+ */
+static tm_sched_fsm_state_processor tm_sched_states[TM_SCHED_FSM_STATE__NUM_OF][TM_SCHED_FSM_EVENT_TYPE__NUM_OF] =
+{
+
+ [TM_SCHED_FSM_STATE_NULL] =
+ {
+ [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_create,
+ [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_state_err,
+
+ },
+ [TM_SCHED_FSM_STATE_INACTIVE] =
+ {
+ [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_inactive_destroy,
+ [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_state_err,
+ },
+ [TM_SCHED_FSM_STATE_ASSIGNED] =
+ {
+ [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_assigned_destroy,
+ [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_assigned_process_util_msg,
+ },
+ [TM_SCHED_FSM_STATE_ACTIVE] =
+ {
+ [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_active_destroy,
+ [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_state_err,
+ },
+
+ [TM_SCHED_FSM_STATE_DELETING] =
+ {
+ [TM_SCHED_FSM_EVENT_TYPE_CREATE] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_DESTROY] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_ASSIGN] = tm_sched_fsm_state_err,
+ [TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG] = tm_sched_fsm_deleting_process_util_msg,
+
+ },
+
+};
+
+static char *state_name_str[] =
+{
+ "TM_SCHED_FSM_STATE_NULL",
+ "TM_SCHED_FSM_STATE_INACTIVE",
+ "TM_SCHED_FSM_STATE_ASSIGNED",
+ "TM_SCHED_FSM_STATE_ACTIVE",
+ "TM_SCHED_FSM_STATE_DELETING",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT(TM_SCHED_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), tm_sched_fsm_state);
+
+static char *tm_sched_state_name_get(tm_sched_fsm_state state)
+{
+ if(state < TM_SCHED_FSM_STATE__LAST)
+ {
+ return state_name_str[state];
+ }
+ else
+ {
+ return "TM_SCHED_UNKNOWN";
+ }
+}
+
+static char *event_name_str[] =
+{
+ "TM_SCHED_FSM_CREATE_EVENT",
+ "TM_SCHED_FSM_DESTROY_EVENT",
+ "TM_SCHED_FSM_ASSIGN_EVENT",
+ "FLOW_FSM_UTIL_MSG_EVENT",
+};
+
+/* Ensure that the name array size matches the associated enum */
+BAL_STATIC_ASSERT(TM_SCHED_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), tm_sched_fsm_event_type);
+
+static char *tm_sched_event_name_get(tm_sched_fsm_event_type event)
+{
+ if(event < TM_SCHED_FSM_EVENT_TYPE__LAST)
+ {
+ return event_name_str[event];
+ }
+ else
+ {
+ return "TM_SCHED_EVT_UNKNOWN";
+ }
+}
+
+
+
+
+/*****************************************************************************/
+/**
+ * @brief A function to initialize the tm sched FSM infrastructure.
+ *
+ * NOTE: This is called once on startup and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno tm_sched_fsm_init(void)
+{
+ int ii;
+ tm_sched_inst *new_entry;
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifdef ENABLE_LOG
+ log_id_tm_sched = bcm_dev_log_id_register("TM_SCHED", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_tm_sched == DEV_LOG_INVALID_ID);
+#endif
+
+ /* Initialize all of the tm_sched queues */
+ TAILQ_INIT(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list);
+ TAILQ_INIT(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list);
+
+ /* Populate the free list with it's initial set of tm_scheds */
+ for(ii=0; ii<TM_SCHED_ALLOCATION_BLOCK_SIZE; ii++)
+ {
+
+ new_entry = bcmos_calloc(sizeof(tm_sched_inst));
+
+ if(NULL == new_entry)
+ {
+ BCM_LOG(FATAL, log_id_tm_sched, "Failed to initialize the tm_sched free list - FATAL\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ tm_sched_free_by_entry(new_entry);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to un-initialize the tm sched FSM infrastructure.
+ *
+ * NOTE: This is called once on shutdown and NOT for each FSM instance.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno tm_sched_fsm_finish(void)
+{
+
+ tm_sched_inst *current_entry, *p_temp_entry;
+
+ /* Free all the entries on the active list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
+ tm_sched_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list, current_entry, tm_sched_inst_next);
+
+ bcmos_free(current_entry);
+
+ }
+
+ /* Free all the entries on the free list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list,
+ tm_sched_inst_next,
+ p_temp_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list, current_entry, tm_sched_inst_next);
+
+ bcmos_free(current_entry);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to retrieve a tm_sched instance of the specified class.
+ *
+ * @param key A pointer to the key of the tm_sched being referenced
+ * @param search_flag A flag specifying the type of tm_sched
+ * instance to be retrieved
+ *
+ * @returns tm_sched_inst_t* A pointer to the found tm_sched instance,
+ * or NULL if one is not found
+ *****************************************************************************/
+tm_sched_inst *tm_sched_inst_get(bcmbal_tm_sched_key key, tm_sched_flag search_flag)
+{
+ tm_sched_inst *current_entry = NULL;
+
+ /*
+ * First, check the active list if the caller has chosen to do so
+ */
+ if(TM_SCHED_FLAG_ACTIVE & search_flag)
+ {
+ TAILQ_FOREACH(current_entry,
+ &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
+ tm_sched_inst_next)
+ {
+
+ if(current_entry->req_tm_sched_info.key.id == key.id
+ && current_entry->req_tm_sched_info.key.dir == key.dir)
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched, "Found active tm_sched\n");
+ /* The tm_sched instance pointer is in current_entry */
+ break;
+ }
+ }
+ }
+
+ /*
+ * Next, check the free list if the caller has chosen to do so
+ */
+ if((TM_SCHED_FLAG_FREE & search_flag) && (NULL == current_entry))
+ {
+ /* Now check the free list */
+ if(!TAILQ_EMPTY(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list))
+ {
+ /* Just grab the first entry */
+ current_entry = TAILQ_FIRST(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list);
+
+ /* Remove it from the free list */
+ TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list, current_entry, tm_sched_inst_next);
+
+ /* And add it to the active list */
+ TAILQ_INSERT_TAIL(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list, current_entry, tm_sched_inst_next);
+
+ /*
+ * Initialize the fsm state
+ */
+ current_entry->fsm_state = TM_SCHED_FSM_STATE_NULL;
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "Using new tm_sched\n");
+
+ }
+ }
+
+ if((TM_SCHED_FLAG_ANY & search_flag) && (NULL == current_entry))
+ {
+ /*A tm_sched was not found on either list */
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "************** ERROR: no tm_sched found\n");
+ }
+
+ return current_entry;
+}
+
+static bcmos_errno bcmbal_tm_sched_validate_sched_parent(const bcmbal_tm_sched_cfg *p_tm_sched_cfg, tm_sched_inst **p_parent_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_key tm_sched_key;
+ tm_sched_key.dir = p_tm_sched_cfg->key.dir;
+ tm_sched_key.id = p_tm_sched_cfg->data.sched_parent.sched_id;
+
+ do
+ {
+ (*p_parent_tm_sched_inst) = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+ if(NULL == (*p_parent_tm_sched_inst))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent dir = %s id = %d does not exist and therefor can not be set at the tm sched parent\n",
+ TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /*check weight/priority setting based on parent sched_type*/
+ if(BCMBAL_TM_SCHED_TYPE_SP == (*p_parent_tm_sched_inst)->req_tm_sched_info.data.sched_type)
+ {
+ if(!BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with a priority, as its sched_parent' sched_type is sp\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent can not be set with a weight, as its sched_parent' sched_type is sp\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(p_tm_sched_cfg->data.sched_parent.priority >= (*p_parent_tm_sched_inst)->req_tm_sched_info.data.num_priorities)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "sched priority (%d) is higher than the allowed at parent sched (id = %d dir = %s num of priorities = %d )\n",
+ p_tm_sched_cfg->data.sched_parent.priority , tm_sched_key.id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir),
+ (*p_parent_tm_sched_inst)->req_tm_sched_info.data.num_priorities);
+
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ if(BCMBAL_TM_SCHED_TYPE_WFQ == (*p_parent_tm_sched_inst)->req_tm_sched_info.data.sched_type)
+ {
+ if(!BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with a weight, as its sched_parent' sched_type is wrr\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent can not be set with a priority, as its sched_parent' sched_type is wrr \n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ if(BCMBAL_TM_SCHED_TYPE_SP_WFQ == (*p_parent_tm_sched_inst)->req_tm_sched_info.data.sched_type)
+ {
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority)
+ && BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with either weight or priority, not both. as its sched_parent' sched_type is sp_wrr\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ if(!BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, priority)
+ && !BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_tm_sched_cfg->data.sched_parent), tm_sched_parent, weight))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched parent must be set with either weight or priority, as its sched_parent' sched_type is sp_wrr\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ }while(0);
+
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief tm_sched_fsm_info_validate
+ *
+ * This routine is used to validate all input attributes required for a tm_sched
+ * settings
+ *
+ * @param p_tm_sched_cfg A pointer to a tm sched object
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+static bcmos_errno tm_sched_fsm_info_validate(const bcmbal_tm_sched_cfg *p_tm_sched_cfg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_owner owner = p_tm_sched_cfg->data.owner;
+ bcmbal_interface_key intf_key;
+ bcmbal_subscriber_terminal_key sub_term_key;
+ sub_term_inst *p_sub_term_inst = NULL;
+ tm_sched_inst *p_tm_sched_inst;
+ bcmos_bool is_sched_type_and_level_mandatory = BCMOS_TRUE;
+
+ do
+ {
+ if(!_rsc_mgr_tm_sched_id_validate(p_tm_sched_cfg->key.id))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Illegal tm sched id (reserved for auto created) \n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, owner))
+ {
+ switch(owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ /*tm sched owned by agg port is the only case sched type might be unset*/
+ is_sched_type_and_level_mandatory = BCMOS_FALSE;
+
+ if(BCMBAL_TM_SCHED_DIR_US != p_tm_sched_cfg->key.dir)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "tm sched owned by agg port must be of US direction, while tm sched id = %d is not\n", p_tm_sched_cfg->key.dir);
+ return BCM_ERR_PARM;
+ }
+ /*agg port owned tm sched can not be part of hqos, therefor can not have sched parent set*/
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_parent))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "tm sched owned by agg port is a tsand alone and can not have sched_parent set to it");
+ return BCM_ERR_PARM;
+ }
+ /*validate all required parameters are set*/
+ if((owner.u.agg_port.intf_id == BAL_API_MAX_INTF_ID)
+ || (owner.u.agg_port.sub_term_id == BCMBAL_SUB_ID_UNKNOWN))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Illegal owner agg port settings intf_id = %d sub_id = %d \n",
+ owner.u.agg_port.intf_id, owner.u.agg_port.sub_term_id);
+ return BCM_ERR_PARM;
+ }
+
+ /*validate interface is up*/
+ intf_key.intf_id = owner.u.agg_port.intf_id;
+ intf_key.intf_type = BCMBAL_INTF_TYPE_PON;
+
+ if(bcmbal_interface_status_get(intf_key)!= BCMBAL_STATUS_UP)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "intf = %d is not UP\n",
+ intf_key.intf_id);
+ return BCM_ERR_NOT_CONNECTED;
+ }
+
+ /*validate sub terminal exist*/
+ sub_term_key.intf_id = owner.u.agg_port.intf_id;
+ sub_term_key.sub_term_id = owner.u.agg_port.sub_term_id;
+
+ p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
+
+ if(!p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed to get subscriber terminal with intf = %d id = %u\n",
+ sub_term_key.intf_id, sub_term_key.sub_term_id);
+ return BCM_ERR_NOENT;
+ }
+ }
+ break;
+
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ /*validate sub terminal exist*/
+ sub_term_key.intf_id = owner.u.uni.intf_id;
+ sub_term_key.sub_term_id = owner.u.uni.sub_term_id;
+
+ p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE);
+
+ if(!p_sub_term_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed to get subscriber terminal with intf = %d id = %u\n",
+ sub_term_key.intf_id, sub_term_key.sub_term_id);
+ return BCM_ERR_NOENT;
+ }
+
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if(BCMOS_TRUE == is_sched_type_and_level_mandatory)
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_type))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched type is a mandatory parameter for setting tm sched\n");
+ ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+ /*if sched type is sp or wrr_sp, num_of_priorities is a mandatory parameter*/
+ if(BCMBAL_TM_SCHED_TYPE_SP == p_tm_sched_cfg->data.sched_type
+ || BCMBAL_TM_SCHED_TYPE_SP_WFQ == p_tm_sched_cfg->data.sched_type)
+ {
+ if(!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, num_priorities))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "num_priorities is a mandatory parameter for setting tm sched with sched type %s\n",
+ BCMBAL_TM_SCHED_TYPE_SP == p_tm_sched_cfg->data.sched_type ? "sp" : "sp_wrr");
+ ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+ }
+ if(!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_child_type))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Sched child type is a mandatory parameter for setting tm sched\n");
+ ret = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+ }
+
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg, tm_sched, sched_parent))
+ {
+ if(BCM_ERR_OK == (ret = bcmbal_tm_sched_validate_sched_parent(p_tm_sched_cfg, &p_tm_sched_inst)))
+ {
+ if(BCM_ERR_OK != (ret = bcmbal_tm_sched_sub_scheds_list_entry_add(p_tm_sched_inst, p_tm_sched_cfg->key.id)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "could not set scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
+ TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_cfg->data.sched_parent.sched_id,
+ TM_SCHED_DIR_TO_STR(p_tm_sched_cfg->key.dir), p_tm_sched_cfg->key.id, bcmos_strerror(ret));
+ break;
+ }
+ }
+ else
+ {
+
+ BCM_LOG(ERROR, log_id_tm_sched, "could not validate scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
+ TM_SCHED_DIR_TO_STR(p_tm_sched_cfg->key.dir), p_tm_sched_cfg->data.sched_parent.sched_id,
+ TM_SCHED_DIR_TO_STR(p_tm_sched_cfg->key.dir), p_tm_sched_cfg->key.id, bcmos_strerror(ret));
+ break;
+ }
+ }
+
+ }while(0);
+
+ return ret;
+
+}
+/*****************************************************************************/
+/**
+ * @brief A function called by the core worker thread to process an
+ * tm_sched object message (SET, GET, CLEAR, STATS) received
+ * from the BAL Public API.
+ *
+ * @param msg_payload Pointer to a BAL message received from the
+ * BAL Public API.
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_tm_sched_object(void *msg_payload)
+{
+ bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK;
+ bcmbal_tm_sched_cfg *p_tm_sched_cfg = (bcmbal_tm_sched_cfg *)msg_payload;
+ tm_sched_inst *p_tm_sched_inst = NULL;
+ tm_sched_fsm_event fsm_event;
+ bcmbal_tm_sched_key tm_sched_key;
+ bcmbal_obj_msg_type oper_type;
+ bcmbal_tm_sched_owner owner;
+ uint32_t ref_count;
+ queue_entry *current_queue_entry;
+ bcmbal_tm_queue_key current_queue_key;
+ tm_queue_inst *current_queue_inst;
+ bcmbal_interface_key intf_key;
+
+ do
+ {
+ BUG_ON(NULL == msg_payload);
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched object\n");
+
+ tm_sched_key = p_tm_sched_cfg->key;
+ oper_type = p_tm_sched_cfg->hdr.hdr.type;
+
+ /*
+ * A message pointer may be passed inside the event structure.
+ */
+ fsm_event.msg = msg_payload;
+
+ /* SET or GET or CLEAR...? */
+ switch(oper_type)
+ {
+ case(BCMBAL_OBJ_MSG_TYPE_SET):
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched SET REQ mgmt message\n");
+ do
+ {
+ if(BCMBAL_STATUS_UP != acc_term_status_get())
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - Access-terminal is not UP. No further processing\n");
+ ret = BCM_ERR_STATE;
+ break;
+ }
+
+ /*Find the specified tm_sched instance is already created */
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+
+ if(NULL != p_tm_sched_inst)
+ {
+ /* This is a fatal error condition */
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - tm sched found. Set after create is currently not supported. No further processing\n");
+ ret = BCM_ERR_NOT_SUPPORTED;
+ break;
+ }
+
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_FREE);
+ if(NULL == p_tm_sched_inst)
+ {
+ /* This is a fatal error condition */
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - tm sched not found. No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "Creating a new tm sched\n");
+
+ BCMBAL_CFG_PROP_SET(p_tm_sched_cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_MANUAL);
+
+ /* Fill in given cfg with current tm sched instance API request data structure and validate it*/
+ bcmbal_tm_sched_object_overlay_w_src_priority(&p_tm_sched_inst->req_tm_sched_info, p_tm_sched_cfg);
+
+ /* Check if the mandatory tm sched attributes have been set, and range check where applicable */
+ if(BCM_ERR_OK != (ret = tm_sched_fsm_info_validate(p_tm_sched_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "tm_sched fsm validation Failed (%d)\n", ret);
+ tm_sched_free_by_entry(p_tm_sched_inst);
+ break;
+ }
+
+
+ /* Perform the validation check(s) that the utils require */
+ if(BCM_ERR_OK != (ret = sw_util_tm_sched_validate(p_tm_sched_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "tm_sched switch validation Failed (%d)\n", ret);
+ tm_sched_free_by_entry(p_tm_sched_inst);
+ break;
+ }
+
+ }while(0);
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+ rsp_ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_sched);
+ if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret)
+ {
+ break;
+ }
+
+ /*
+ * Initial checks complete. Process the request
+ */
+ fsm_event.event_type = TM_SCHED_FSM_EVENT_TYPE_CREATE;
+ /*
+ * Run the tm sched FSM to process this event
+ */
+ ret = tm_sched_fsm_exec(p_tm_sched_inst, &fsm_event);
+
+ }//SET
+ break;
+
+ case(BCMBAL_OBJ_MSG_TYPE_GET):
+ {
+ bcmbal_tm_queue_id_list_u8 queues_list = {};
+ bcmbal_tm_sched_id_list_u8 sub_scheds_list = {};
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched GET REQ mgmt message\n");
+
+ /* Just return the tm sched data info that we have on record for tm sched instance */
+ /*Find the specified tm sched instance */
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched not found on GET\n");
+ ret = BCM_ERR_NOENT;
+ }
+ else
+ {
+ /* Return the queues list if requested */
+ BCMBAL_CFG_PROP_CLEAR(&p_tm_sched_inst->req_tm_sched_info,
+ tm_sched,
+ queues);
+
+ /* If the user requested the list of queues for this tm sched then return the list.*/
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg,
+ tm_sched,
+ queues))
+ {
+
+ if(BCM_ERR_OK == queues_list_fill(p_tm_sched_inst, &queues_list))
+ {
+ /* NOTE: The returned list may be empty */
+ BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info,
+ tm_sched,
+ queues,
+ queues_list);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Error trying to fill queues list to return\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ /* Return the sub scheds list if requested */
+ BCMBAL_CFG_PROP_CLEAR(&p_tm_sched_inst->req_tm_sched_info,
+ tm_sched,
+ sub_scheds);
+
+ /* If the user requested the list of sub scheds for this tm sched then return the list.*/
+ if(BCMBAL_CFG_PROP_IS_SET(p_tm_sched_cfg,
+ tm_sched,
+ sub_scheds))
+ {
+
+ if(BCM_ERR_OK == sub_scheds_list_fill(p_tm_sched_inst, &sub_scheds_list))
+ {
+ /* NOTE: The returned list may be empty */
+ BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info,
+ tm_sched,
+ sub_scheds,
+ sub_scheds_list);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Error trying to fill sub_scheds list to return\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ /* We respond to the BAL public API backend with a result. We always
+ * send a complete msg_payload back to the API, but the data portion
+ * of the object is only relevant when a GET or GET-STATS has been requested.
+ */
+
+ p_tm_sched_inst->req_tm_sched_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr;
+ *((bcmbal_tm_sched_cfg *)msg_payload) = p_tm_sched_inst->req_tm_sched_info;
+
+ }
+
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_sched);
+
+ /* Free the temporary lists if they were used */
+ if(queues_list.val)
+ {
+ bcmos_free(queues_list.val);
+ }
+ }//GET
+ break;
+
+ case(BCMBAL_OBJ_MSG_TYPE_CLEAR):
+ {
+ do
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched, "Processing a tm sched CLEAR REQ mgmt message\n");
+ /*Find the specified tm sched instance */
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched not found on Clear\n");
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /*user can not clear auto created sched owned by agg port*/
+ if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
+ {
+ owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+ if(BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT == owner.type
+ && BCMBAL_TM_CREATION_MODE_AUTO == p_tm_sched_inst->req_tm_sched_info.data.creation_mode)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is auto created, therefor can not be manually deleted\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /*check that a tm is not active,
+ if that tm owned by interface, it is active if any of its queue is active.
+ if it is owned by agg port, it is active if the agg port id has ref count > 1 */
+ switch(owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ rsc_mgr_alloc_id_get_ref_count(owner.u.agg_port.intf_id,owner.u.agg_port.agg_port_id,&ref_count);
+ if(ref_count > 1)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is active and therefor can not be deleted (if = %d agg id = %d, ref count = %d \n",
+ owner.u.agg_port.intf_id,owner.u.agg_port.agg_port_id, ref_count);
+ ret = BCM_ERR_PARM;
+ }
+ break;
+ }//BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT
+
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ TAILQ_FOREACH(current_queue_entry,
+ &p_tm_sched_inst->queues_list,
+ next)
+ {
+ if(NULL != current_queue_entry)
+ {
+ current_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
+ current_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
+ current_queue_key.id = current_queue_entry->queue_id;
+ current_queue_inst = tm_queue_inst_get(current_queue_key, TM_QUEUE_FLAG_ACTIVE);
+ if(NULL == current_queue_inst)
+ {
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ if(TM_QUEUE_FSM_STATE_IN_USE == current_queue_inst->fsm_state)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is active (has an in use queue) and therefor can not be deleted (queue id = %d \n",
+ current_queue_key.id);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ }//TAILQ_FOREACH
+ if(BCM_ERR_OK == ret)
+ {
+ /*TM_SCHEDs (either auto or manually created) with owner interface may only be deleted there are no attached TM_QUEUEs, and only when the associated interface is in the ADMIN-DOWN state*/
+ intf_key.intf_type = owner.u.interface.intf_type;
+ intf_key.intf_id = owner.u.interface.intf_id;
+ if(BCMBAL_STATUS_DOWN != bcmbal_interface_status_get(intf_key))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Specified tm_sched is owned by interface that is not admin down, and can be removed only when the associated interface is in the ADMIN-DOWN state\n");
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ }//BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE
+ break;
+
+ default:
+ break;
+ }//switch owner.type
+ }//owner is set
+ /*generate destroy event*/
+ if(BCM_ERR_OK == ret)
+ {
+ fsm_event.event_type = TM_SCHED_FSM_EVENT_TYPE_DESTROY;
+ fsm_event.msg = msg_payload;
+ ret = tm_sched_fsm_exec(p_tm_sched_inst,&fsm_event);
+ }
+ }while(0);
+
+ mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_tm_sched);
+ }//CLEAR
+ break;
+
+ default:
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Unsupported operation on tm sched object (%d)\n",
+ oper_type);
+ ret = BCM_ERR_NOT_SUPPORTED;
+ }
+ }
+ }while(0);
+ BCM_LOG(DEBUG, log_id_tm_sched, "%s returns\n", __FUNCTION__);
+
+ return ret;
+}
+
+
+static void tm_sched_inst_entry_obj_init(tm_sched_inst *p_entry)
+{
+ /* The actual key content is irrelevant for free tm_scheds */
+ bcmbal_tm_sched_key key = { .id = 0, .dir = BCMBAL_TM_SCHED_DIR_DS};
+
+ BCMBAL_CFG_INIT(&p_entry->current_tm_sched_info,
+ tm_sched,
+ key);
+ p_entry->fsm_state = TM_SCHED_FSM_STATE_NULL;
+ /* Initialize the queues and suc scheds lists */
+ p_entry->num_queues_on_node = 0;
+ TAILQ_INIT(&p_entry->queues_list);
+
+ p_entry->num_sub_scheds_on_node = 0;
+ TAILQ_INIT(&p_entry->sub_scheds_list);
+
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_tm_sched_info), BCMOS_FALSE);
+}
+/*****************************************************************************/
+/**
+ * @brief A function to free a tm_sched instance specified by a the supplied
+ * entry pointer.
+ *
+ * @param p_entry A pointer to the entry to be freed
+ *
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_sched_free_by_entry(tm_sched_inst *p_entry)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *current_entry;
+ tm_sched_inst *p_temp_entry;
+ /*
+ * First, check the active list (an active tm_sched can be in the adding or removing state)
+ */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
+ tm_sched_inst_next,
+ p_temp_entry)
+ {
+ if(current_entry == p_entry)
+ {
+ /* Remove it from the active list */
+ TAILQ_REMOVE(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list, current_entry, tm_sched_inst_next);
+ break;
+ }
+ }
+ tm_sched_inst_entry_obj_init(p_entry);
+
+ /* And add it to the free list */
+ TAILQ_INSERT_TAIL(&TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->free_tm_sched_list, p_entry, tm_sched_inst_next);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The tm sched FSM state processing executive function
+ *
+ * @param p_tm_sched_inst Pointer to a tm_sched instance
+ * @param p_event Pointer to a tm_sched event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_sched_fsm_exec(tm_sched_inst *p_tm_sched_inst, tm_sched_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_fsm_state pre_state;
+ tm_sched_fsm_state_processor tm_sched_state_processor;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_tm_sched_inst);
+ BUG_ON(NULL == p_event);
+
+ /* Record the present state for debug printing
+ */
+ pre_state = p_tm_sched_inst->fsm_state;
+
+ /*
+ * Get the state processing function
+ */
+ tm_sched_state_processor = tm_sched_states[p_tm_sched_inst->fsm_state][p_event->event_type];
+
+ /*
+ * If there's a state processing function for this event and state, execute it.
+ * Otherwise, process a generic error.
+ */
+ if(tm_sched_state_processor)
+ {
+ ret = tm_sched_state_processor(p_tm_sched_inst, p_event->msg, p_event);
+ }
+ else
+ {
+ tm_sched_fsm_state_err(p_tm_sched_inst, p_event->msg, p_event);
+ }
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "*** Error detected during state processing\n");
+ p_tm_sched_inst->fsm_state = pre_state;
+ }
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "*** Event %s, State: %s --> %s\n\n",
+ tm_sched_event_name_get(p_event->event_type),
+ tm_sched_state_name_get(pre_state),
+ tm_sched_state_name_get(p_tm_sched_inst->fsm_state));
+
+ return ret;
+}
+
+
+
+/*****************************************************************************/
+/**
+ * @brief The tm sched FSM function which is executed when an error
+ * is encountered during FSM processing.
+ *
+ * @param p_tm_sched_inst Pointer to a tm_sched instance
+ * @param msg Pointer to a BAL message received from one of
+ * the BAL apps.
+ * @param p_event Pointer to a tm_sched event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_sched_fsm_state_err(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event)
+{
+ bcmos_errno ret = BCM_ERR_INVALID_OP;
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "Error encountered processing TM_SCHED FSM"
+ " - BAD EVENT ()\n");
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to process a tm sched object event received
+ * from one of the BAL apps.
+ *
+ * @param msg_payload A pointer to the util message
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno process_tm_sched_util_msg(void *msg_payload)
+{
+
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_msg_type type;
+ bcmbal_tm_sched_key key;
+ tm_sched_inst *p_tm_sched_inst;
+ tm_sched_fsm_event tm_sched_event;
+
+
+ BUG_ON(NULL == msg_payload);
+ do
+ {
+ type = bcmbal_type_minor_get(msg_payload);
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "Processing a tm sched %s util message from %s\n",
+ bcmbal_msg_t_str[type],
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+
+ if(BAL_MSG_TYPE_IND == type)
+ {
+
+ /* recover the key from the message */
+ key = ((bal_util_msg_ind *)msg_payload)->obj_key.tm_sched_key;
+
+
+ /*
+ * Get the sub_term instance that's being referenced
+ */
+ p_tm_sched_inst = tm_sched_inst_get(key, TM_SCHED_FLAG_ACTIVE);
+
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "invalid tm sched (dir %s id %d) found while processing a util message type %s from %s\n",
+ TM_SCHED_DIR_TO_STR(key.dir),
+ key.id,
+ bcmbal_msg_t_str[type],
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ tm_sched_event.msg = msg_payload;
+
+ tm_sched_event.event_type = TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG;
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "p_tm_sched_inst->fsm_state=%d, tm_sched_event.event_type = %d\n",
+ p_tm_sched_inst->fsm_state, tm_sched_event.event_type);
+ /*Run the tm sched FSM to process this event */
+ if(BCM_ERR_OK == ret)
+ {
+ ret = tm_sched_fsm_exec(p_tm_sched_inst, &tm_sched_event);
+ }
+ }
+
+ else
+ {
+ ret = BCM_ERR_NOT_SUPPORTED;
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Unknown message type received from the APP (not one of RSP:ACK:IND:AUTO_IND) (type:%d)\n",
+ type);
+ }
+ }while(0);
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief The tm sched FSM state processing for a tm sched create command received
+ * from the BAL Public API.
+ *
+ * @param p_tm_sched_inst Pointer to a tm sched instance
+ * @param msg Pointer to a BAL message received from the BAL Public API
+ * @param p_event Pointer to a tm sched event structure
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+static bcmos_errno tm_sched_fsm_create(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_INACTIVE;
+
+ if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched,owner))
+ {
+ ret = bcmbal_tm_sched_set_owner(p_tm_sched_inst);
+ }
+
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_sched_set_owner(tm_sched_inst *p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_owner owner;
+ bcmbal_tm_queue_key tm_queue_key;
+ bcmbal_tm_sched_key tm_sched_key = p_tm_sched_inst->req_tm_sched_info.key;
+ queue_entry *current_queue_entry;
+
+
+ BUG_ON(NULL == p_tm_sched_inst);
+ do
+ {
+ if( BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched,owner))
+ {
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_ASSIGNED;
+ owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+ switch(owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ /*no need to validate owner attributes as these are read only and set by VALID internal objects*/
+ if(BCM_ERR_OK != (ret = sw_util_tm_sched_set(p_tm_sched_inst)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "error %s detected by switch util while adding tm sched\n", bcmos_strerror(ret));
+ break;
+ }
+ /* The hardware has properly accepted the object info, so the request object becomes the current state. */
+ bcmbal_tm_sched_object_overlay_w_src_priority(&p_tm_sched_inst->current_tm_sched_info,
+ &p_tm_sched_inst->req_tm_sched_info);
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_ACTIVE;
+ /*configure all assigned queues*/
+
+ TAILQ_FOREACH(current_queue_entry,
+ &p_tm_sched_inst->queues_list,
+ next)
+ {
+ tm_queue_key.id = current_queue_entry->queue_id;
+ tm_queue_key.sched_id = tm_sched_key.id;
+ tm_queue_key.sched_dir = tm_sched_key.dir;
+ if(BCM_ERR_OK != (ret = bcmbal_tm_queue_set_owner(tm_queue_key)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Could not set queue sched id = %d sched dir = %s queue id = %d of the tm sched (%s)\n",
+ tm_queue_key.sched_id, TM_SCHED_DIR_TO_STR(tm_queue_key.sched_dir), tm_queue_key.id, bcmos_strerror(ret));
+ break;
+ }
+ }
+ BCMBAL_OBJ_IN_PROGRESS_SET(&(p_tm_sched_inst->current_tm_sched_info), BCMOS_FALSE);
+ p_tm_sched_inst->current_tm_sched_info.hdr.hdr.status = ret;
+
+ }
+ break;
+
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ bcmbal_interface_key intf_key = {.intf_type = BCMBAL_INTF_TYPE_PON, .intf_id = owner.u.agg_port.intf_id};
+ bcmbal_subscriber_terminal_key sub_key = {.sub_term_id = owner.u.agg_port.sub_term_id, .intf_id = intf_key.intf_id};
+ /*for agg port, should validate intf and sub term validity*/
+ if(NULL == sub_term_inst_get(&sub_key, SUB_TERM_FLAG_ACTIVE))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Can not set an agg port for onu (if-%d id-%d) which does not exist\n", intf_key.intf_id, sub_key.sub_term_id);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ BCM_LOG(DEBUG, log_id_tm_sched, "Getting a new ALLOC ID from resource manager\n");
+
+ owner.u.agg_port.agg_port_id = 0; /* 0 is a magic number telling the resource manager that it should provide the initial allocation of the ALLOC ID */
+ ret = rsc_mgr_alloc_id_alloc(intf_key.intf_id, &owner.u.agg_port.agg_port_id, 1, NULL);
+
+ if(BCM_ERR_OK != ret)
+ {
+ /* An error has occurred trying to get mandatory data */
+ BCM_LOG(ERROR, log_id_tm_sched, "Failed to get ALLOC ID from resource manager\n");
+ ret = BCM_ERR_NORES;
+ break;
+ }
+ /*set the agg port id into the inst*/
+ BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner, owner);
+
+ ret = mac_util_agg_port_set(p_tm_sched_inst, BAL_UTIL_OPER_AGG_PORT_ADD);
+ if(BCM_ERR_OK != ret)
+ {
+ /* An error has occurred trying to configure mac*/
+ BCM_LOG(ERROR, log_id_tm_sched, "Failed to configure ALLOC ID at mac (%s)\n",bcmos_strerror(ret));
+ break;
+ }
+ }
+ break;
+
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ default:
+ BCM_LOG(ERROR, log_id_tm_sched, "nothing to do with owner type %d \n", p_tm_sched_inst->current_tm_sched_info.data.owner.type);
+ return BCM_ERR_PARM;
+ break;
+ }
+ }
+ }while(0);
+
+ return ret;
+}
+
+
+bcmos_errno bcmbal_tm_sched_unset_owner(tm_sched_inst *p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_owner *owner;
+ bcmbal_tm_queue_key tm_queue_key;
+ queue_entry *current_queue_entry;
+ tm_sched_inst *p_parent_tm_sched_inst;
+
+ BUG_ON(NULL == p_tm_sched_inst);
+
+ tm_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
+ tm_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
+
+ do
+ {
+ if( BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
+ {
+ owner = &(p_tm_sched_inst->req_tm_sched_info.data.owner);
+ switch(owner->type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ /*remove all assigned queues*/
+ TAILQ_FOREACH(current_queue_entry,
+ &p_tm_sched_inst->queues_list,
+ next)
+ {
+ tm_queue_key.id = current_queue_entry->queue_id;
+ if(BCM_ERR_OK != (ret = bcmbal_tm_queue_unset_owner(tm_queue_key)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Could not unset queue sched id = %d sched dir = %s queue id = %d of the tm sched (%s) \n",
+ tm_queue_key.sched_id, TM_SCHED_DIR_TO_STR(tm_queue_key.sched_dir), tm_queue_key.id, bcmos_strerror(ret));
+ break;
+ }
+ }
+ /*unset from parent scheduler*/
+ if(BCMBAL_CFG_PROP_IS_SET(&(p_tm_sched_inst->req_tm_sched_info), tm_sched, sched_parent))
+ {
+ if(BCM_ERR_OK == (ret = bcmbal_tm_sched_validate_sched_parent(&(p_tm_sched_inst->req_tm_sched_info), &p_parent_tm_sched_inst)))
+ {
+ if(BCM_ERR_OK == (ret = bcmbal_tm_sched_sub_scheds_list_entry_remove(p_parent_tm_sched_inst, p_tm_sched_inst->req_tm_sched_info.key.id)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "could not remove scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
+ TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.data.sched_parent.sched_id,
+ TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.key.id, bcmos_strerror(ret));
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "could not validate scheduler dir = %s id = %d as parent of sched dir = %s id = %d (err= %s)\n",
+ TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.data.sched_parent.sched_id,
+ TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.key.id, bcmos_strerror(ret));
+ }
+ }
+
+ /*no need to validate owner attributes as these are read only and set by VALID internal objects*/
+ if(BCM_ERR_OK != (ret = sw_util_tm_sched_clear(p_tm_sched_inst)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "error %s detected by switch util while clearing tm sched\n", bcmos_strerror(ret));
+ break;
+ }
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_INACTIVE;
+
+ }
+ break;
+
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ default:
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "nothing to do with unsetting owner type %d \n",
+ p_tm_sched_inst->current_tm_sched_info.data.owner.type);
+ ret = BCM_ERR_PARM;
+ }
+ break;
+ }
+ }
+ }while(0);
+ return ret;
+
+}
+
+/*for the auto create, only key dir is set, id will be allocated from rsc mgr*/
+bcmos_errno bcmbal_tm_sched_auto_create(bcmbal_tm_sched_cfg cfg, tm_sched_inst **p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+ cfg.key.id = 0; /* 0 is a magic number telling the resource manager that it should provide the initial allocation of the tm sched id*/
+ if(BCM_ERR_OK != (ret = _rsc_mgr_tm_sched_auto_id_alloc(&cfg.key.id)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,"Could not allocate a tm sched auto id \n");
+ break;
+ }
+ *p_tm_sched_inst = tm_sched_inst_get(cfg.key, TM_SCHED_FLAG_FREE);
+ if(NULL == p_tm_sched_inst)
+ {
+ /* This is a fatal error condition */
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - could not allocate tm sched No further processing\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "\n Tm Sched id %d dir %s was created \n", cfg.key.id, TM_SCHED_DIR_TO_STR(cfg.key.dir));
+
+ (*p_tm_sched_inst)->req_tm_sched_info = cfg;
+ ret = tm_sched_fsm_create(*p_tm_sched_inst, NULL,NULL);
+ }while(0);
+ return ret;
+}
+
+static bcmos_errno bcmbal_tm_sched_queues_list_entry_add(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_queue_key queue_key)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ queue_entry *current_entry;
+
+ do
+ {
+ /* Check if the id is already on the list before adding it */
+ TAILQ_FOREACH(current_entry,
+ &p_tm_sched_inst->queues_list,
+ next)
+ {
+ if(current_entry->queue_id == queue_key.id)
+ {
+ return BCM_ERR_ALREADY;
+ }
+ }
+
+ /* Get a new entry and configure it */
+ current_entry = bcmos_calloc(sizeof(queue_entry));
+
+ if(NULL == current_entry)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "No memory available to add queue\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ current_entry->queue_id = queue_key.id;
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "adding queue id %u to tm sched %u\n", queue_key.id, p_tm_sched_inst->req_tm_sched_info.key.id);
+
+ /* Save the entry on the list of queues ids on this sched*/
+ TAILQ_INSERT_TAIL(&p_tm_sched_inst->queues_list,
+ current_entry, next);
+ (p_tm_sched_inst->num_queues_on_node)++;
+ } while(0);
+ return ret;
+}
+
+static bcmos_errno bcmbal_tm_sched_queues_list_entry_remove(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_queue_key queue_key)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ queue_entry *current_entry, *p_temp_entry;
+
+ do
+ {
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &p_tm_sched_inst->queues_list,
+ next,
+ p_temp_entry)
+ {
+ if(current_entry->queue_id == queue_key.id)
+ {
+ /* Remove it from the list of queues ids on this sched*/
+ TAILQ_REMOVE(&p_tm_sched_inst->queues_list,
+ current_entry, next);
+
+ bcmos_free(current_entry);
+
+ (p_tm_sched_inst->num_queues_on_node)--;
+ ret = BCM_ERR_OK;
+ break;
+
+ }
+ }
+ } while(0);
+
+ return ret;
+}
+
+static bcmos_errno queues_list_fill(tm_sched_inst *p_tm_sched_inst,
+ bcmbal_tm_queue_id_list_u8 *queues_list)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ queue_entry *current_entry = NULL;
+ int ii = 0;
+
+ do
+ {
+
+ /* Traverse the list of queues recorded and fill in the list to be returned */
+ queues_list->len = p_tm_sched_inst->num_queues_on_node;
+ queues_list->val = bcmos_calloc(sizeof(bcmbal_tm_queue_id) * queues_list->len);
+
+ if(NULL == queues_list->val)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ TAILQ_FOREACH(current_entry,
+ &p_tm_sched_inst->queues_list,
+ next)
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "adding queue %d to response at array location %d\n",
+ current_entry->queue_id,
+ ii);
+ queues_list->val[ii++] = current_entry->queue_id;
+ }
+ } while(0);
+ return ret;
+}
+
+static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_add(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ sub_sched_entry *current_entry;
+
+ BUG_ON(NULL == p_tm_sched_inst);
+
+ do
+ {
+ /* Check if the id is already on the list before adding it */
+ TAILQ_FOREACH(current_entry,
+ &p_tm_sched_inst->sub_scheds_list,
+ next)
+ {
+ if(current_entry->sched_id == sched_id)
+ {
+ return BCM_ERR_ALREADY;
+ }
+ }
+
+ /* Get a new entry and configure it */
+ current_entry = bcmos_calloc(sizeof(sub_sched_entry));
+
+ if(NULL == current_entry)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "No memory available to add sub sched\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ current_entry->sched_id = sched_id;
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "adding sub sched id %u to tm sched dir = %s id = %u\n",
+ sched_id, TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir), p_tm_sched_inst->req_tm_sched_info.key.id);
+
+ /* Save the entry on the list of sub_scheds on that tm sched */
+ TAILQ_INSERT_TAIL(&p_tm_sched_inst->sub_scheds_list,
+ current_entry, next);
+ (p_tm_sched_inst->num_sub_scheds_on_node)++;
+
+ } while(0);
+ return ret;
+}
+
+static bcmos_errno bcmbal_tm_sched_sub_scheds_list_entry_remove(tm_sched_inst *p_tm_sched_inst, bcmbal_tm_sched_id sched_id)
+{
+ bcmos_errno ret = BCM_ERR_NOENT;
+ sub_sched_entry *current_entry, *p_temp_entry;
+
+ do
+ {
+
+ /* Check if the id is on the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &p_tm_sched_inst->sub_scheds_list,
+ next,
+ p_temp_entry)
+ {
+ if(current_entry->sched_id == sched_id)
+ {
+ /* Remove it from the list of sub_scheds ids on this sched*/
+ TAILQ_REMOVE(&p_tm_sched_inst->sub_scheds_list,
+ current_entry, next);
+
+ bcmos_free(current_entry);
+
+ (p_tm_sched_inst->num_sub_scheds_on_node)--;
+ ret = BCM_ERR_OK;
+ break;
+
+ }
+ }
+ } while(0);
+
+ return ret;
+}
+
+static bcmos_errno sub_scheds_list_fill(tm_sched_inst *p_tm_sched_inst,
+ bcmbal_tm_sched_id_list_u8 *sub_scheds_list)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ sub_sched_entry *current_entry = NULL;
+ int ii = 0;
+
+ do
+ {
+
+ /* Traverse the list of sub_scheds_ids recorded and fill in the list to be returned */
+ sub_scheds_list->len = p_tm_sched_inst->num_sub_scheds_on_node;
+ sub_scheds_list->val = bcmos_calloc(sizeof(bcmbal_tm_sched_id) * sub_scheds_list->len);
+
+ if(NULL == sub_scheds_list->val)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "No memory available\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ TAILQ_FOREACH(current_entry,
+ &p_tm_sched_inst->sub_scheds_list,
+ next)
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "adding sub sched %d to response at array location %d\n",
+ current_entry->sched_id,
+ ii);
+ sub_scheds_list->val[ii++] = current_entry->sched_id;
+ }
+
+ } while(0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_sched_set_queue(tm_queue_inst *p_tm_queue_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *p_tm_sched_inst = NULL;
+ bcmbal_tm_sched_key tm_sched_key;
+ BUG_ON(NULL == p_tm_queue_inst);
+ do
+ {
+ tm_sched_key.id = p_tm_queue_inst->api_req_tm_queue_info.key.sched_id;
+ tm_sched_key.dir= p_tm_queue_inst->api_req_tm_queue_info.key.sched_dir;
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - could not find an active tm sched (dir = %s id = %d) to attach the queue (id = %d)\n",
+ TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id,p_tm_queue_inst->api_req_tm_queue_info.key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ ret = bcmbal_tm_sched_queues_list_entry_add(p_tm_sched_inst, p_tm_queue_inst->api_req_tm_queue_info.key);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - could not add the queue entry to the sched\n");
+ break;
+ }
+ if(TM_SCHED_FSM_STATE_ACTIVE == p_tm_sched_inst->fsm_state)
+ {
+ if(BCM_ERR_OK != (ret = bcmbal_tm_queue_activate(p_tm_queue_inst)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - could not activate the newly added queue \n");
+ break;
+ }
+ }
+ }while(0);
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_sched_remove_queue(tm_queue_inst *p_tm_queue_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *p_tm_sched_inst = NULL;
+ bcmbal_tm_sched_key tm_sched_key;
+ BUG_ON(NULL == p_tm_queue_inst);
+ do
+ {
+ tm_sched_key.id = p_tm_queue_inst->api_req_tm_queue_info.key.sched_id;
+ tm_sched_key.dir= p_tm_queue_inst->api_req_tm_queue_info.key.sched_dir;
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+
+ if(NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - could not find an active tm sched (dir = %s id = %d) to attach the queue (id = %d)\n",
+ TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id,p_tm_queue_inst->api_req_tm_queue_info.key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ if(BCM_ERR_OK != (ret = bcmbal_tm_sched_queues_list_entry_remove(p_tm_sched_inst, p_tm_queue_inst->api_req_tm_queue_info.key)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "ERROR - could not remove the queue entry from the sched\n");
+ break;
+ }
+
+ }while(0);
+ return ret;
+}
+
+/*tm_sched_find_by_owner - currently might be called for agg port and uni port only*/
+static tm_sched_inst* tm_sched_find_by_owner(bcmbal_tm_sched_owner owner)
+{
+ tm_sched_inst *current_entry = NULL;
+
+ TAILQ_FOREACH(current_entry,
+ &TM_SCHED_FSM_TM_SCHED_LIST_CTX_PTR->active_tm_sched_list,
+ tm_sched_inst_next)
+ {
+ if(BCMBAL_CFG_PROP_IS_SET(¤t_entry->req_tm_sched_info, tm_sched,owner))
+ {
+ switch(current_entry->req_tm_sched_info.data.owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ if((owner.u.agg_port.intf_id == current_entry->req_tm_sched_info.data.owner.u.agg_port.intf_id)
+ && (owner.u.agg_port.agg_port_id == current_entry->req_tm_sched_info.data.owner.u.agg_port.agg_port_id))
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched, "Found active tm_sched dir = us id= %d for agg_port_id %d intf_id %d\n",
+ current_entry->req_tm_sched_info.key.id, owner.u.agg_port.agg_port_id, owner.u.agg_port.intf_id);
+ return current_entry;
+ }
+ }
+ break;
+
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ if((owner.u.uni.intf_id == current_entry->req_tm_sched_info.data.owner.u.uni.intf_id)
+ && (owner.u.uni.sub_term_id == current_entry->req_tm_sched_info.data.owner.u.uni.sub_term_id)
+ && (owner.u.uni.idx == current_entry->req_tm_sched_info.data.owner.u.uni.idx))
+ {
+ BCM_LOG(DEBUG, log_id_tm_sched, "Found active tm_sched id = %d for uni intf_id = %d sub_id = %d uni_id = %d\n",
+ current_entry->req_tm_sched_info.key.id, owner.u.uni.intf_id, owner.u.uni.sub_term_id, owner.u.uni.idx);
+ return current_entry;
+ }
+ }
+
+ default:
+ break;
+ }
+ }
+ }
+ return current_entry;
+}
+
+tm_sched_inst* tm_sched_find_agg_port_node(uint8_t intf_id, bcmbal_aggregation_port_id agg_port_id)
+{
+ bcmbal_tm_sched_owner owner;
+ owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT;
+ owner.u.agg_port.intf_id = intf_id;
+ owner.u.agg_port.agg_port_id = agg_port_id;
+
+ return tm_sched_find_by_owner(owner);
+}
+
+
+
+static bcmos_errno tm_sched_fsm_assigned_process_util_msg(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
+{
+
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_tm_sched_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ " Received a IND message from BAL UTIL (%s) during %s state\n",
+ subsystem_str[bcmbal_sender_get(msg)],
+ tm_sched_state_name_get(p_tm_sched_inst->fsm_state));
+
+ /* Handle response */
+ ret = ind_msg->status;
+
+ if(BCM_ERR_OK == ret)
+ {
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_ACTIVE;
+ bcmbal_tm_sched_object_overlay_w_src_priority(&p_tm_sched_inst->current_tm_sched_info,
+ &p_tm_sched_inst->req_tm_sched_info);
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed in state %s;%s\n",
+ tm_sched_state_name_get(p_tm_sched_inst->fsm_state),
+ bcmos_strerror(ret));
+ }
+
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&p_tm_sched_inst->current_tm_sched_info.hdr,
+ log_id_tm_sched);
+
+ return ret;
+}
+
+/*currently handling util msg of alloc id setting complete only for agg port tm sched only*/
+static bcmos_errno tm_sched_fsm_deleting_process_util_msg(tm_sched_inst *p_tm_sched_inst,
+ void *msg,
+ tm_sched_fsm_event *p_event)
+{
+ bcmos_errno ret;
+ bal_util_msg_ind *ind_msg;
+
+ /* Parameter checks */
+ BUG_ON(NULL == p_tm_sched_inst);
+ BUG_ON(NULL == msg);
+ BUG_ON(NULL == p_event);
+
+ do
+ {
+ ind_msg = (bal_util_msg_ind *)msg;
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ " Received a IND message from BAL UTIL (%s) during %s state\n",
+ subsystem_str[bcmbal_sender_get(msg)],
+ tm_sched_state_name_get(p_tm_sched_inst->fsm_state));
+
+ /* Handle response */
+ ret = ind_msg->status;
+
+ if(BCM_ERR_OK == ret)
+ {
+ ret = tm_sched_fsm_destroy(p_tm_sched_inst);
+ }
+ else
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed in state %s;%s\n",
+ tm_sched_state_name_get(p_tm_sched_inst->fsm_state),
+ bcmos_strerror(ret));
+ }
+ }while(0);
+ return ret;
+}
+
+static bcmos_errno tm_sched_fsm_destroy(tm_sched_inst *p_tm_sched_inst)
+{
+ queue_entry *current_entry = NULL;
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_queue_key tm_queue_key;
+ tm_queue_inst *p_tm_queue_inst;
+ int i=0;
+ bcmbal_tm_sched_owner owner;
+
+ do
+ {
+ switch(p_tm_sched_inst->req_tm_sched_info.data.owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_NULL;
+ owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+
+ ret = rsc_mgr_alloc_id_free(owner.u.agg_port.intf_id, owner.u.agg_port.agg_port_id, NULL);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed to free alloc id if=%d id=%d at resource manager",
+ owner.u.agg_port.intf_id, owner.u.agg_port.agg_port_id);
+ break;
+ }
+ ret = tm_sched_fsm_destroy(p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed to free auto created tm sched id, id=%d at resource manager",
+ p_tm_sched_inst->req_tm_sched_info.key.id);
+ break;
+ }
+ break;
+ }
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ tm_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
+ tm_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
+
+ /*delete all attached queues*/
+ TAILQ_FOREACH(current_entry,
+ &p_tm_sched_inst->queues_list,
+ next)
+ {
+
+ BCM_LOG(DEBUG, log_id_tm_sched,
+ "deleting queue %u (location %u)\n",
+ current_entry->queue_id,
+ i);
+ tm_queue_key.id = current_entry->queue_id;
+
+ p_tm_queue_inst = tm_queue_inst_get(tm_queue_key, TM_QUEUE_FLAG_ACTIVE);
+ if(NULL == p_tm_queue_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,"ERROR - tm queue not found. No further processing\n");
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ ret = bcmbal_tm_queue_destroy(p_tm_queue_inst, BCMOS_FALSE);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,"ERROR - could not destroy tm queue %d .No further processing\n",
+ tm_queue_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ bcmos_free(current_entry);
+ i++;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ if(p_tm_sched_inst->req_tm_sched_info.data.creation_mode == BCMBAL_TM_CREATION_MODE_AUTO)
+ {
+ ret = _rsc_mgr_tm_sched_auto_id_free(p_tm_sched_inst->req_tm_sched_info.key.id);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed to free auto created tm sched id, id=%d at resource manager ",
+ p_tm_sched_inst->req_tm_sched_info.key.id);
+ break;
+ }
+ }
+
+ mgmt_msg_send_balapi_ind(ret,
+ (void *)&p_tm_sched_inst->req_tm_sched_info.hdr,
+ log_id_tm_sched);
+
+ ret = tm_sched_free_by_entry(p_tm_sched_inst);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "Failed to free tm sched id=%d dir = %s",p_tm_sched_inst->req_tm_sched_info.key.id,
+ TM_SCHED_DIR_TO_STR(p_tm_sched_inst->req_tm_sched_info.key.dir));
+ break;
+ }
+ }while(0);
+ return ret;
+
+}
+
+static bcmos_errno tm_sched_fsm_inactive_destroy(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
+{
+ return tm_sched_fsm_destroy(p_tm_sched_inst);
+}
+
+static bcmos_errno tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
+{
+ return bcmbal_tm_sched_fsm_active_destroy(p_tm_sched_inst);
+}
+
+static bcmos_errno tm_sched_fsm_assigned_destroy(tm_sched_inst *p_tm_sched_inst, void *msg, tm_sched_fsm_event *p_event)
+{
+ bcmos_errno ret = bcmbal_tm_sched_fsm_active_destroy(p_tm_sched_inst);
+ if (BCM_ERR_OK == ret)
+ ret = tm_sched_fsm_destroy(p_tm_sched_inst);
+
+ return ret;
+
+}
+bcmos_errno bcmbal_tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_owner owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+ bcmbal_interface_key intf_key;
+
+
+ switch(owner.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ uint32_t ref_count;
+ ret = rsc_mgr_alloc_id_get_ref_count(p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.intf_id,
+ p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.agg_port_id, &ref_count);
+ if(1!= ref_count)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "Cant destroy tm sched owned by agg port (if %d id %d) "
+ "with reference count %d (greated than 1)\n",
+ p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.intf_id,
+ p_tm_sched_inst->req_tm_sched_info.data.owner.u.agg_port.agg_port_id, ref_count);
+ ret = BCM_ERR_INTERNAL;
+ break;
+
+ }
+ ret = mac_util_agg_port_set(p_tm_sched_inst, BAL_UTIL_OPER_AGG_PORT_REMOVE);
+ if(BCM_ERR_OK != ret)
+ {
+ /* An error has occurred trying to configure mac*/
+ BCM_LOG(ERROR, log_id_tm_sched, "Failed to remove ALLOC ID at mac (%s)\n",bcmos_strerror(ret));
+ break;
+ }
+ else
+ {
+ p_tm_sched_inst->fsm_state = TM_SCHED_FSM_STATE_DELETING;
+ }
+ break;
+ }
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ /*remove the setting of the sched from the owner configuration*/
+ intf_key.intf_type = owner.u.interface.intf_type;
+ intf_key.intf_id = owner.u.interface.intf_id;
+ ret = interface_tm_sched_unset(intf_key, p_tm_sched_inst->req_tm_sched_info.key);
+ tm_sched_fsm_destroy(p_tm_sched_inst);
+ break;
+ }
+
+ default:
+ break;
+ }
+ return ret;
+
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to set an interface as a tm sched owner
+ *
+ * @param interface_key the interface to become the owner
+ * @param p_tm_sched_inst the tm sched instance to be set
+ *
+ * @returns bcmos_errno
+ *****************************************************************************/
+bcmos_errno bcmbal_tm_sched_set_interface_owner(bcmbal_interface_key interface_key, tm_sched_inst *p_tm_sched_inst)
+{
+ BUG_ON(NULL == p_tm_sched_inst);
+
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_tm_sched_owner owner;
+ do
+ {
+ if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
+ {
+ owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+ if (BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE!= owner.type )
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "tm sched %s%d is already assigned with an owner of type %d",
+ p_tm_sched_inst->current_tm_sched_info.key.dir == BCMBAL_TM_SCHED_DIR_US ? "us" : "ds",
+ p_tm_sched_inst->current_tm_sched_info.key.id, owner.type );
+ break;
+ }
+ if(owner.u.interface.intf_type != interface_key.intf_type
+ || owner.u.interface.intf_id != interface_key.intf_id)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched, "tm sched %s%d is already assigned with an interface owner",
+ p_tm_sched_inst->current_tm_sched_info.key.dir == BCMBAL_TM_SCHED_DIR_US ? "us" : "ds",
+ p_tm_sched_inst->current_tm_sched_info.key.id);
+
+ ret = BCM_ERR_ALREADY;
+ break;
+ }
+ }
+ else
+ {
+ owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE;
+ owner.u.interface.intf_type = interface_key.intf_type;
+ owner.u.interface.intf_id = interface_key.intf_id;
+ BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner, owner);
+ ret = bcmbal_tm_sched_set_owner(p_tm_sched_inst);
+ }
+ }while(0);
+ return ret;
+}
+
+#define BCMBAL_INTERFACE_DEFAULT_NUM_OF_TM_QUEUES 4
+#define BCMBAL_INTERFACE_DEFAULT_SCHED_TYPE BCMBAL_TM_SCHED_TYPE_SP_WFQ
+#define BCMBAL_INTERFACE_DEFAULT_SCHED_CHILD_TYPE BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE
+
+#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_SIZE 128
+#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_SBR 128
+#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_PBR 128
+#define BCMBAL_TM_QUEUE_AUTO_DEFAULT_BURST_SIZE 128
+
+bcmos_errno bcmbal_tm_sched_interface_tm_auto_create(bcmbal_interface_cfg *p_interface_info)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *p_tm_sched_inst = NULL;
+ bcmbal_tm_sched_cfg tm_sched_default_cfg;
+ bcmbal_tm_queue_cfg tm_queue_default_cfg;
+ bcmbal_tm_shaping default_shaping;
+ bcmbal_tm_sched_key tm_sched_key;
+ bcmbal_tm_queue_key tm_queue_key;
+ int i;
+
+ do
+ {
+ /*create the auto tm sched*/
+ tm_sched_key.dir = p_interface_info->key.intf_type == BCMBAL_INTF_TYPE_PON ? BCMBAL_TM_SCHED_DIR_DS : BCMBAL_TM_SCHED_DIR_US;
+ BCMBAL_CFG_INIT(&tm_sched_default_cfg, tm_sched, tm_sched_key);
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, sched_type, BCMBAL_INTERFACE_DEFAULT_SCHED_TYPE);
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, sched_child_type, BCMBAL_INTERFACE_DEFAULT_SCHED_CHILD_TYPE);
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, num_priorities, BCMBAL_INTERFACE_DEFAULT_NUM_OF_TM_QUEUES);
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_sched, creation_mode, BCMBAL_TM_CREATION_MODE_AUTO);
+
+ if (BCM_ERR_OK != (ret = bcmbal_tm_sched_auto_create(tm_sched_default_cfg, &p_tm_sched_inst)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,"Could not create the auto tm sched \n");
+ break;
+ }
+ if (tm_sched_key.dir == BCMBAL_TM_SCHED_DIR_US)
+ {
+ BCMBAL_CFG_PROP_SET(p_interface_info, interface, us_tm, p_tm_sched_inst->req_tm_sched_info.key.id);
+ }
+ else
+ {
+ BCMBAL_CFG_PROP_SET(p_interface_info, interface, ds_tm, p_tm_sched_inst->req_tm_sched_info.key.id);
+ }
+
+ /*SET THE DEFAULT ATTRIBUTES FOR AUTO CREATED QUEUE*/
+ tm_queue_key.sched_id = p_tm_sched_inst->req_tm_sched_info.key.id;
+ tm_queue_key.sched_dir = p_tm_sched_inst->req_tm_sched_info.key.dir;
+ default_shaping.sbr = (uint8_t)BCMBAL_TM_QUEUE_AUTO_DEFAULT_SBR;
+ default_shaping.pbr = (uint8_t)BCMBAL_TM_QUEUE_AUTO_DEFAULT_PBR;
+ default_shaping.burst = (uint8_t)BCMBAL_TM_QUEUE_AUTO_DEFAULT_BURST_SIZE;
+ BCMBAL_CFG_PROP_SET(&tm_queue_default_cfg, tm_queue, rate, default_shaping);
+ BCMBAL_CFG_PROP_SET(&tm_sched_default_cfg, tm_queue, creation_mode, BCMBAL_TM_CREATION_MODE_AUTO);
+
+ /*create its queues*/
+ for(i=0; i<BCMBAL_INTERFACE_DEFAULT_NUM_OF_TM_QUEUES; i++)
+ {
+ tm_queue_key.id = i;
+ BCMBAL_CFG_INIT(&tm_queue_default_cfg, tm_queue, tm_queue_key);
+
+ BCMBAL_CFG_PROP_SET(&tm_queue_default_cfg, tm_queue, priority, i);
+ BCMBAL_CFG_PROP_SET(&tm_queue_default_cfg, tm_queue, rate, default_shaping);
+ if (BCM_ERR_OK != (ret = bcmbal_tm_queue_auto_create(tm_queue_default_cfg)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,"Could not create the %d tm queue\n", i);
+ break;
+ }
+ }
+
+ ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst);
+
+ }while(0);
+
+ return ret;
+}
+
+bcmos_errno bcmbal_tm_sched_set_sub_term_owner( bcmbal_tm_sched_key tm_sched_key, const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ tm_sched_inst *p_tm_sched_inst;
+ bcmbal_tm_sched_owner owner;
+
+ do
+ {
+ p_tm_sched_inst = tm_sched_inst_get(tm_sched_key, TM_SCHED_FLAG_ACTIVE);
+ if (NULL == p_tm_sched_inst)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "tm sched dir = %s id = %d which is set as the subscriber tm does not exist \n",
+ TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ if(BCMBAL_CFG_PROP_IS_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner))
+ {
+ /*check if it is already owned by that sub term*/
+ owner = p_tm_sched_inst->req_tm_sched_info.data.owner;
+ if (owner.type != BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "tm sched dir = %s id = %d which is set as the subscriber tm already owned with owner type %d\n",
+ TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id, owner.type);
+ ret = BCM_ERR_PARM;
+ break;
+
+ }
+ if (owner.u.sub_term.intf_id != p_sub_term_cfg->key.intf_id
+ || owner.u.sub_term.sub_term_id != p_sub_term_cfg->key.sub_term_id)
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "tm sched dir = %s id = %d which is set as the subscriber tm already owned by sub_term intf_id = %d sub_term_id = %d\n",
+ TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id, owner.u.sub_term.intf_id, owner.u.sub_term.sub_term_id);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else
+ {
+ owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM;
+ owner.u.sub_term.intf_id = p_sub_term_cfg->key.intf_id;
+ owner.u.sub_term.sub_term_id = p_sub_term_cfg->key.sub_term_id;
+ BCMBAL_CFG_PROP_SET(&p_tm_sched_inst->req_tm_sched_info, tm_sched, owner, owner);
+
+ if (BCM_ERR_OK!= (ret = bcmbal_tm_sched_set_owner(p_tm_sched_inst)))
+ {
+ BCM_LOG(ERROR, log_id_tm_sched,
+ "could not set sub term intf_id = %d sub_term_id = %d as the owner of tm sched dir = %s id = %d which is set as the subscriber tm \n",
+ owner.u.sub_term.intf_id, owner.u.sub_term.sub_term_id, TM_SCHED_DIR_TO_STR(tm_sched_key.dir), tm_sched_key.id);
+ break;
+ }
+ }
+ }while (0);
+ return ret;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/main/tm_sched_fsm.h b/bal_release/src/core/main/tm_sched_fsm.h
new file mode 100644
index 0000000..ea39a4f
--- /dev/null
+++ b/bal_release/src/core/main/tm_sched_fsm.h
@@ -0,0 +1,156 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file tm_sched_fsm.h
+ * @brief Code to support the BAL TM Sched FSM
+ *
+ */
+
+#ifndef TM_SCHED_FSM_H
+#define TM_SCHED_FSM_H
+
+/*@{*/
+
+#include <bcmos_system.h>
+#include <bal_api.h>
+#include <tm_queue_fsm.h>
+
+/* set the total pool size of available tm sched instances to 4k */
+#define TM_SCHED_ALLOCATION_BLOCK_SIZE (4096)
+
+typedef enum
+{
+ TM_SCHED_FSM_EVENT_TYPE_NONE = -1,
+ TM_SCHED_FSM_EVENT_TYPE_CREATE ,
+ TM_SCHED_FSM_EVENT_TYPE_DESTROY ,
+ TM_SCHED_FSM_EVENT_TYPE_ASSIGN ,
+ TM_SCHED_FSM_EVENT_TYPE_UTIL_MSG ,
+
+ TM_SCHED_FSM_EVENT_TYPE__LAST,
+ TM_SCHED_FSM_EVENT_TYPE__NUM_OF
+} tm_sched_fsm_event_type;
+
+
+
+typedef enum
+{
+ TM_SCHED_FSM_STATE_NONE = -1,
+ TM_SCHED_FSM_STATE_NULL ,
+ TM_SCHED_FSM_STATE_INACTIVE ,
+ TM_SCHED_FSM_STATE_ASSIGNED ,
+ TM_SCHED_FSM_STATE_ACTIVE ,
+ TM_SCHED_FSM_STATE_DELETING ,
+
+ TM_SCHED_FSM_STATE__LAST,
+ TM_SCHED_FSM_STATE__NUM_OF
+} tm_sched_fsm_state;
+
+
+typedef enum
+{
+ TM_SCHED_FLAG_ACTIVE = 1<<0, /**< A tm_sched is on the active list */
+ TM_SCHED_FLAG_FREE = 1<<1, /**< A tm_sched is on the free list */
+ TM_SCHED_FLAG_ANY = (TM_SCHED_FLAG_ACTIVE | TM_SCHED_FLAG_FREE), /**< A tm_sched is on either the active or free list */
+} tm_sched_flag;
+
+
+typedef struct tm_sched_fsm_event_t
+{
+ tm_sched_fsm_event_type event_type; /**< The tm_sched fsm events */
+ void *msg;
+
+ /* other necessary information */
+} tm_sched_fsm_event;
+
+typedef struct queue_entry
+{
+ bcmbal_tm_queue_id queue_id;
+ TAILQ_ENTRY(queue_entry) next; /**< TAILQ link */
+}queue_entry;
+
+typedef struct sub_sched_entry
+{
+ bcmbal_tm_sched_id sched_id;
+ TAILQ_ENTRY(sub_sched_entry) next; /**< TAILQ link */
+}sub_sched_entry;
+
+typedef struct tm_sched_inst tm_sched_inst;
+struct tm_sched_inst
+{
+ bcmbal_tm_sched_cfg current_tm_sched_info; /**< The current information for this tm_sched (used for GET) */
+ bcmbal_tm_sched_cfg req_tm_sched_info; /**< The last tm_sched object info received from the Public API */
+ uint16_t num_queues_on_node; /**< The number of queues attached to this node */
+ TAILQ_HEAD(queues_list_head, queue_entry) queues_list;
+ uint16_t num_sub_scheds_on_node; /**< The number of sub schedulers for this tm sched */
+ TAILQ_HEAD(sub_scheds_list_head, sub_sched_entry) sub_scheds_list;
+ tm_sched_fsm_state fsm_state; /**< The tm_sched FSM state */
+ TAILQ_ENTRY(tm_sched_inst) tm_sched_inst_next; /**< TAILQ link */
+};
+
+
+/*
+ * Group FSM data structures
+ */
+typedef struct tm_sched_fsm_ctx
+{
+ /* Lists of free tm_sched entries and active tm_sched entries
+ */
+ TAILQ_HEAD(free_tm_sched_list_head, tm_sched_inst) free_tm_sched_list;
+
+ TAILQ_HEAD(active_tm_sched_list_head, tm_sched_inst) active_tm_sched_list;
+
+} tm_sched_fsm_ctx;
+
+
+/* Function declarations */
+
+extern bcmos_errno tm_sched_fsm_init(void);
+extern bcmos_errno tm_sched_fsm_finish(void);
+extern bcmos_errno process_tm_sched_util_msg(void *msg_payload);
+extern bcmos_errno process_tm_sched_object(void *msg_payload);
+
+tm_sched_inst *tm_sched_inst_get(bcmbal_tm_sched_key key, tm_sched_flag search_flag);
+bcmos_errno bcmbal_tm_sched_auto_create(bcmbal_tm_sched_cfg cfg, tm_sched_inst **p_tm_sched_inst);
+bcmos_errno bcmbal_tm_sched_set_owner(tm_sched_inst *p_tm_sched_inst);
+bcmos_errno bcmbal_tm_sched_unset_owner(tm_sched_inst *p_tm_sched_inst);
+bcmos_errno bcmbal_tm_sched_set_queue(tm_queue_inst *p_tm_queue_inst);
+bcmos_errno bcmbal_tm_sched_remove_queue(tm_queue_inst *p_tm_queue_inst);
+tm_sched_inst * tm_sched_find_agg_port_node(uint8_t intf_id, bcmbal_aggregation_port_id agg_port_id);
+bcmos_errno bcmbal_tm_sched_fsm_active_destroy(tm_sched_inst *p_tm_sched_inst);
+
+
+
+#define TM_SCHED_DIR_TO_STR(dir) ((dir) == BCMBAL_TM_SCHED_DIR_DS ? "ds" : "us")
+/*@}*/
+
+#endif /*TM_SCHED_FSM_H */
+
diff --git a/bal_release/src/core/platform/bcmos_platform.h b/bal_release/src/core/platform/bcmos_platform.h
new file mode 100644
index 0000000..a2e95b4
--- /dev/null
+++ b/bal_release/src/core/platform/bcmos_platform.h
@@ -0,0 +1,99 @@
+/******************************************************************************
+ *
+ * <: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 BCMOS_PLATFORM_H_
+#define BCMOS_PLATFORM_H_
+
+#ifndef BCMOS_SYSTEM_H_
+#error Please do not include bcmos_platform.h directly. Include bcmos_system.h
+#endif
+
+#include <bal_osmsg.h>
+
+/** BAL CORE CPU core
+ * \ingroup system_task */
+typedef enum
+{
+ BCMOS_CPU_CORE_ANY, /**< Any core */
+
+ BCMOS_CPU_CORE__NUM_OF = 1, /**< Number of cores */
+} bcmos_core;
+
+/*
+ * BAL CORE modules
+ *
+ * \ingroup system_module
+ */
+typedef enum
+{
+ BCMOS_MODULE_ID_NONE, /**< no module */
+
+ BCMOS_MODULE_ID_WORKER_MGMT, /** worker module for MGMT message handling */
+ BCMOS_MODULE_ID_WORKER_API_IND, /** worker module for BAL API INDICATION message handling */
+ BCMOS_MODULE_ID_WORKER_BAL_CORE_FOR_AGENT, /** worker module for the BAL CORE when running as an OF agent */
+ BCMOS_MODULE_ID_USER_APPL_EON, /** EON module */
+ BCMOS_MODULE_ID_USER_APPL_EPON_OAM, /** EPON OAM module */
+ BCMOS_MODULE_ID_OFPAL, /** OF-PAL module */
+ BCMOS_MODULE_ID_OMCI_TRANSPORT, /** OMCI Transport module */
+
+ BCMOS_MODULE_ID__NUM_OF, /**< Number of modules */
+ BCMOS_MODULE_ID_INVALID = BCMOS_MODULE_ID_NONE
+} bcmos_module_id;
+
+/*
+ * BAL CORE event group. Each group supports up to 32 events.
+ *
+ * \ingroup system_event
+ */
+typedef enum
+{
+ BCMOS_EVENT_FIRST,
+
+ BCMOS_EVENT_ID__NUM_OF, /**< Number of event groups */
+} bcmos_event_id;
+
+/** Message hash size
+ * \ingroup system_msg
+ */
+#define BCMOS_MSG_HASH_SIZE 512
+
+/*
+ * Task priorities
+ */
+#define TASK_PRIORITY_IPC_RX BCMOS_TASK_PRIORITY_3
+#define TASK_PRIORITY_CLI BCMOS_TASK_PRIORITY_15
+#define TASK_PRIORITY_WORKER BCMOS_TASK_PRIORITY_16
+#define TASK_PRIORITY_USER_APPL_EON BCMOS_TASK_PRIORITY_17
+#define TASK_PRIORITY_OFPAL BCMOS_TASK_PRIORITY_18
+#define TASK_PRIORITY_OMCI_TRANSPORT BCMOS_TASK_PRIORITY_20
+#define TASK_PRIORITY_DEV_LOG BCMOS_TASK_PRIORITY_30
+
+#endif /* BCMOS_PLATFORM_H_ */
diff --git a/bal_release/src/core/util/mac/Makefile b/bal_release/src/core/util/mac/Makefile
new file mode 100644
index 0000000..8594d20
--- /dev/null
+++ b/bal_release/src/core/util/mac/Makefile
@@ -0,0 +1,43 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# BAL core CLI application
+#
+MOD_NAME = bal_mac_util
+MOD_TYPE = lib
+MOD_DEPS = dev_log utils maple_sdk os_cli bal_api bal_app_utils balutils topology
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../main
+
+srcs = bal_mac_util.c bal_mac_util_gpon.c bal_mac_util_xgpon.c bal_mac_util_common_itu_pon.c bal_mac_util_db_apis.c bal_mac_util_loopback.c bal_mac_util_epon.c
+
+ifeq ("$(SWITCH)", "qax")
+ MOD_DEFS += -DQAX_SWITCH
+endif
+
diff --git a/bal_release/src/core/util/mac/bal_mac_util.c b/bal_release/src/core/util/mac/bal_mac_util.c
new file mode 100644
index 0000000..3824996
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util.c
@@ -0,0 +1,2467 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util.c
+ *
+ * @brief mac util interfaces definition used by Bal Core
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+#include <bal_mac_util_common_itu_pon.h>
+#include <bal_mac_util_epon.h>
+
+#include <bal_worker.h>
+#include <bal_core.h>
+#include <bal_cli.h>
+
+#ifdef BOARD
+#include <bcmolt_board.h>
+#include <bcmolt_board_cli.h>
+#endif
+#include <bcm_api_cli.h>
+#include <bcmolt_dev_selector.h>
+#include <bcmolt_host_sw_version.h>
+#include <bcmolt_model_revision.h>
+
+#ifdef ENABLE_LOG
+
+#define INBOLD_BAD(a) "\033[31m"a"\033[0m"
+/*
+ * mac util logging for generic logging, as well as on per PON basis
+ */
+dev_log_id log_id_mac_util;
+dev_log_id log_id_mac_util_pon_if[NUM_SUPPORTED_SUBSCRIBER_INTERFACES];
+
+/** @def size of log Id string */
+#define MAC_UTIL_LOG_STR_SZ 64
+
+/** @def to make a log string for a PON interface, to register with logging module during initialization */
+#define MAC_UTIL_MAKE_LOG_STR_FOR_PON_IF(_pon_if_id, _buf, _buf_sz) \
+ do \
+ { \
+ int n = 0; \
+ n = snprintf((_buf), (_buf_sz), "MAC_UTIL_PON_%d", (_pon_if_id)); \
+ BUG_ON((0 > n) || ((_buf_sz) <= n)); \
+ } while (0); \
+
+static bcmos_errno mac_util_register_logging_per_pon (void);
+#endif //ENABLE_LOG
+
+/* This is not exposed in the object model, so we can use BCMOLT_SYSTEM_MODE__NUM_OF as a special value for loopback. */
+#define BCMOLT_SYSTEM_MODE_LOOPBACK BCMOLT_SYSTEM_MODE__NUM_OF
+#define BCM_TOPO_PON_MODE_LOOPBACK BCM_TOPO_PON_MODE__NUM_OF
+
+static bcmos_errno mac_util_indication_handle_for_device (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_system_mode_get(bcmolt_devid device_id);
+
+/* Maple CLI directory */
+static bcmcli_entry *maple_dir;
+
+/** @brief array stores the list of device related auto indications from Maple to subscribe */
+static mac_util_ind_obj_and_handlers mac_util_device_ind_handlers[] =
+{
+ {BCMOLT_OBJ_ID_DEVICE, "BCMOLT_OBJ_ID_DEVICE", mac_util_indication_handle_for_device}
+};
+
+
+
+#if !defined(WRX_BUILD)
+/* external structures to be used with bcmos_tr
+ * specifying IP:Port assignments of the remote mac device */
+extern uint32_t bcmtr_olt_ip[BCMTR_MAX_OLTS];
+extern uint16_t bcmtr_olt_udp_port[BCMTR_MAX_OLTS];
+extern uint16_t bcmtr_host_udp_port;
+#endif
+
+
+
+/**
+ * @brief BAL request handlers for system mode specific set & validate
+ **/
+static mac_util_bal_req_handlers_for_system_mode_t mac_util_bal_req_handlers_for_system_mode[] =
+{
+ [BCMOLT_SYSTEM_MODE_GPON__16_X] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_gpon_16,
+ .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_gpon
+ },
+ [BCMOLT_SYSTEM_MODE_GPON__8_X] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_gpon_8,
+ .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_gpon
+ },
+ [BCMOLT_SYSTEM_MODE_XGPON_1__8_X] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_xgpon_8,
+ .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_xgpon_xgs
+ },
+ [BCMOLT_SYSTEM_MODE_XGS__2_X_10_G] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_xgs,
+ .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_xgpon_xgs
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_8_tdma,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_4_tdma,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__16_X] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_16_1g,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__8_X] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_8_1g,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__4_X] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_4_1g,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__8_X_10_G] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_8_10g,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__4_X_10_G] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_4_10g,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_EPON__2_X_10_G] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_epon_2_10g,
+ .acc_term_post_indication_set = NULL
+ },
+ [BCMOLT_SYSTEM_MODE_LOOPBACK] =
+ {
+ .acc_term_set = mac_util_access_terminal_set_for_loopback,
+ .acc_term_post_indication_set = NULL
+ }
+};
+
+/**
+ * @brief BAL request handlers for PON protocol specific set & validate
+ *
+ * @note The handling would be like object-oriented programming. The common
+ * handling would be done in the top level call. And then based on protocol,
+ * the mac specific handling will be done in the corresponding mac specific
+ * handler functions.
+ **/
+mac_util_handlers_per_pon_mode_t mac_util_bal_req_handlers_for_pon_mode [BCM_TOPO_PON_MODE__NUM_OF + 1] =
+{
+ [BCM_TOPO_PON_MODE_GPON] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_gpon,
+ .sub_term_validate = mac_util_validate_subscriber_terminal_info_for_gpon,
+ .sub_term_set = mac_util_subscriber_terminal_set_for_gpon,
+ .flow_validate = mac_util_validate_flow_info_for_gpon,
+ .flow_set = mac_util_flow_set_for_gpon,
+ .group_validate = NULL,
+ .group_set = mac_util_group_set_for_gpon,
+ .sla_us_rate_factor = 1
+ },
+ [BCM_TOPO_PON_MODE_XGPON] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_xgpon,
+ .sub_term_validate = mac_util_validate_subscriber_terminal_info_for_xgpon,
+ .sub_term_set = mac_util_subscriber_terminal_set_for_xgpon,
+ .flow_validate = mac_util_validate_flow_info_for_xgpon,
+ .flow_set = mac_util_flow_set_for_xgpon,
+ .group_validate = NULL,
+ .group_set = mac_util_group_set_for_xgpon,
+ .sla_us_rate_factor = 2
+ },
+ [BCM_TOPO_PON_MODE_XGS] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_xgpon,
+ .sub_term_validate = mac_util_validate_subscriber_terminal_info_for_xgpon,
+ .sub_term_set = mac_util_subscriber_terminal_set_for_xgpon,
+ .flow_validate = mac_util_validate_flow_info_for_xgpon,
+ .flow_set = mac_util_flow_set_for_xgpon,
+ .group_validate = NULL,
+ .group_set = mac_util_group_set_for_xgpon,
+ .sla_us_rate_factor = 8
+ },
+ [BCM_TOPO_PON_MODE_EPON_TDMA] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_epon,
+ .sub_term_validate = NULL,
+ .sub_term_set = NULL,
+ .flow_validate = NULL,
+ .flow_set = NULL,
+ .group_validate = NULL,
+ .group_set = NULL,
+ .sla_us_rate_factor = 0
+ },
+ [BCM_TOPO_PON_MODE_EPON_1G] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_epon,
+ .sub_term_validate = NULL,
+ .sub_term_set = NULL,
+ .flow_validate = NULL,
+ .flow_set = NULL,
+ .group_validate = NULL,
+ .group_set = NULL,
+ .sla_us_rate_factor = 0
+ },
+ [BCM_TOPO_PON_MODE_EPON_10G] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_epon,
+ .sub_term_validate = NULL,
+ .sub_term_set = NULL,
+ .flow_validate = NULL,
+ .flow_set = NULL,
+ .group_validate = NULL,
+ .group_set = NULL,
+ .sla_us_rate_factor = 0
+ },
+ [BCM_TOPO_PON_MODE_LOOPBACK] =
+ {
+ .if_validate = NULL,
+ .if_set = mac_util_interface_set_for_loopback,
+ .sub_term_validate = NULL,
+ .sub_term_set = mac_util_subscriber_terminal_set_for_loopback,
+ .flow_validate = NULL,
+ .flow_set = mac_util_flow_set_for_loopback,
+ .group_validate = NULL,
+ .group_set = NULL,
+ .sla_us_rate_factor = 1
+ }
+};
+
+static f_bcmolt_msg_handler g_indication_handler;
+
+static bcm_topo_pon_mode mac_util_get_pon_mode(uint32_t logical_intf_id)
+{
+ bcm_topo_pon_mode mode;
+ if (bcmbal_is_mac_in_loopback())
+ mode = BCM_TOPO_PON_MODE_LOOPBACK;
+ else
+ mode = bcm_topo_pon_get_pon_mode(logical_intf_id);
+ return mode;
+}
+
+static uint16_t oper_status_from_pon_state_get(uint32_t logical_intf_id, uint16_t state)
+{
+ uint16_t oper_status;
+ bcm_topo_pon_family pon_family;
+
+ pon_family = bcm_topo_pon_get_pon_family(logical_intf_id);
+
+ switch (pon_family)
+ {
+ case BCM_TOPO_PON_FAMILY_EPON:
+ oper_status = (((bcmolt_epon_ni_en_state)state == BCMOLT_EPON_NI_EN_STATE_ENABLED) ?
+ BAL_UTIL_OPER_IF_UP : BAL_UTIL_OPER_IF_DOWN);
+ break;
+
+ case BCM_TOPO_PON_FAMILY_GPON:
+ oper_status = (((bcmolt_pon_state)state == BCMOLT_PON_STATE_ACTIVE_WORKING) ?
+ BAL_UTIL_OPER_IF_UP : BAL_UTIL_OPER_IF_DOWN);
+ break;
+
+ case BCM_TOPO_PON_FAMILY_INVALID:
+ default:
+ BCMOS_TRACE_ERR("Unknown PON family on intf %u: %d\n", logical_intf_id, pon_family);
+ oper_status = BAL_UTIL_OPER_IF_DOWN;
+ break;
+ }
+
+ return oper_status;
+}
+
+/*****************************************************************************/
+/**
+ * @brief Function to send a util indication message to the core
+ *
+ * @param msg_payload A pointer to a well formed MAC util indication message
+ *
+ * @returns bcmos_errno == BCM_ERR_OK
+ *
+ *****************************************************************************/
+static bcmos_errno mac_util_ind_send(bal_util_msg_ind *msg_payload)
+{
+ bcmos_errno rc;
+
+ rc = bcmos_msg_dispatch(bcmbal_bcmos_hdr_get(msg_payload), BCMOS_MSG_SEND_AUTO_FREE);
+
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Couldn't dispatch indication message from MAC util (%d:%d)\n",
+ (int)(bcmbal_bcmos_hdr_get(msg_payload))->type,
+ (int)(bcmbal_bcmos_hdr_get(msg_payload))->instance);
+ }
+
+ return rc;
+}
+
+/*****************************************************************************/
+/**
+ * @brief Function to send a util auto indication message to the core
+ *
+ * @param msg_payload A pointer to a well formed MAC util indication message
+ *
+ * @returns bcmos_errno == BCM_ERR_OK
+ *
+ *****************************************************************************/
+static bcmos_errno mac_util_auto_ind_send(bal_util_msg_auto_ind *msg_payload)
+{
+ bcmos_errno rc;
+
+ rc = bcmos_msg_dispatch(bcmbal_bcmos_hdr_get(msg_payload), BCMOS_MSG_SEND_AUTO_FREE);
+
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Couldn't dispatch auto indication message from MAC util (%d:%d)\n",
+ (int)(bcmbal_bcmos_hdr_get(msg_payload))->type,
+ (int)(bcmbal_bcmos_hdr_get(msg_payload))->instance);
+ }
+
+ return rc;
+}
+
+/* Report acc_term event */
+void mac_util_report_acc_term_event(uint16_t event)
+{
+ bal_util_msg_ind *p_bal_util_ind_msg;
+
+ if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind))))
+ {
+ p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION;
+
+ /* device connect */
+ if (BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE == event)
+ {
+ p_bal_util_ind_msg->status = BCM_ERR_OK;
+ }
+ else
+ {
+ p_bal_util_ind_msg->status = BCM_ERR_PARM;
+ }
+
+ bcmbal_msg_hdr_set(p_bal_util_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_ACCESS_TERMINAL,
+ BAL_UTIL_OPER_ACC_TERM_CONNECT,
+ 0);
+
+ BCM_LOG(INFO, log_id_mac_util, "Reporting to Core: BAL_UTIL_OPER_ACC_TERM_CONNECT indication. Status=%s\n",
+ bcmos_strerror(p_bal_util_ind_msg->status));
+
+ mac_util_ind_send(p_bal_util_ind_msg);
+
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Could not allocate memory for access-terminal IND message\n");
+ }
+}
+
+
+/**
+ * @brief Report interface event
+ * @note we consider both err and result for reporting the status to Core
+ * */
+void mac_util_report_if_event(bcmbal_intf_id intf_id,
+ bcmbal_intf_type intf_type,
+ bcmos_errno err,
+ bcmolt_result result,
+ bcmolt_pon_state new_state)
+{
+ bal_util_msg_ind *p_bal_util_ind_msg;
+
+ if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind))))
+ {
+
+ /** @todo validate inf_id is within range based on intf_type */
+ p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION;
+ p_bal_util_ind_msg->obj_key.if_key.intf_id = intf_id;
+ p_bal_util_ind_msg->obj_key.if_key.intf_type = intf_type;
+
+ if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != result))
+ {
+ err = BCM_ERR_INTERNAL;
+ }
+ p_bal_util_ind_msg->status = err;
+
+ bcmbal_msg_hdr_set(p_bal_util_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_INTERFACE,
+ oper_status_from_pon_state_get(intf_id, new_state),
+ 0);
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_id), "Reporting to Core: interface id %d %s indication: %s\n",
+ intf_id,
+ (BAL_UTIL_OPER_IF_UP == oper_status_from_pon_state_get(intf_id, new_state)) ? "UP" : "DOWN",
+ bcmos_strerror(p_bal_util_ind_msg->status));
+
+
+ mac_util_ind_send(p_bal_util_ind_msg);
+
+ }
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_id),
+ "Could not allocate memory for interface IND message\n");
+ }
+}
+
+/* Report subscriber terminal event */
+
+/**
+ * @note p_serial_number may be NULL and is only valid when an ONU
+ * is being reported as DISCOVERED
+ * @note result is config status reported by Maple, whereas err is messaging status
+ * between the MAC util & Maple
+ * */
+void mac_util_report_sub_term_event(bcmbal_intf_id pon_ni,
+ bcmbal_sub_id onu_id,
+ bcmolt_serial_number *p_serial_number,
+ bal_util_oper_sub_term oper,
+ bcmos_errno err,
+ bcmolt_result result,
+ bcmolt_activation_fail_reason fail_reason,
+ bcmolt_epon_tunnel_id tunnel_id)
+{
+ bal_util_msg_ind *p_bal_util_ind_msg;
+ uint16_t total_msglen;
+ bcm_topo_pon_family pon_family;
+
+ total_msglen = sizeof(bal_util_msg_ind);
+
+ pon_family = bcm_topo_pon_get_pon_family(pon_ni);
+ /**
+ * @note if pon mode is invalid then this error should have been caught in the validation stage itself.
+ * However, still checking here to make sure and report an error if needed.
+ */
+ if (pon_family == BCM_TOPO_PON_FAMILY_INVALID)
+ {
+ result = BCMOLT_RESULT_FAIL;
+ }
+
+ if (pon_family == BCM_TOPO_PON_FAMILY_EPON)
+ {
+ total_msglen += sizeof(bcmolt_epon_tunnel_id);
+ }
+ else if(NULL != p_serial_number)
+ {
+ total_msglen += sizeof(bcmbal_serial_number);
+ }
+
+
+ /* consolidate "err" and "result" into one report status */
+ if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != result))
+ {
+ err = BCM_ERR_INTERNAL;
+ }
+
+
+ if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(total_msglen)))
+ {
+ /* set the object key */
+ p_bal_util_ind_msg->obj_key.sub_term_key.intf_id = pon_ni;
+ p_bal_util_ind_msg->obj_key.sub_term_key.sub_term_id = onu_id;
+
+ /* set bal util msg version */
+ p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION;
+
+ bcmbal_msg_hdr_set(p_bal_util_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ (BAL_UTIL_OPER_SUB_TERM_DISCOVERY == oper) ? BAL_MSG_TYPE_AUTO_IND : BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL,
+ oper,
+ 0);
+
+ /*
+ * Set all the message header parameters
+ */
+ if ((BCM_ERR_OK == err) &&
+ (((BAL_UTIL_OPER_SUB_TERM_ADD == oper) && (fail_reason == BCMOLT_ACTIVATION_FAIL_REASON_NONE)) ||
+ ((BAL_UTIL_OPER_SUB_TERM_ADD != oper) && (fail_reason == MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE))) )
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_ni),
+ "Reporting to Core: %s "
+ "indication from mac util: Success\n",
+ (BAL_UTIL_OPER_SUB_TERM_ADD == oper) ? "BAL_UTIL_OPER_SUB_TERM_ADD" :
+ (BAL_UTIL_OPER_SUB_TERM_REMOVE == oper) ? "BAL_UTIL_OPER_SUB_TERM_REMOVE" :
+ "BAL_UTIL_OPER_SUB_TERM_DISCOVERY");
+
+ p_bal_util_ind_msg->status = BCM_ERR_OK;
+
+ if (pon_family == BCM_TOPO_PON_FAMILY_EPON)
+ {
+ memcpy(&p_bal_util_ind_msg->data, &tunnel_id, sizeof(bcmolt_epon_tunnel_id));
+ }
+ else if (NULL != p_serial_number)
+ {
+ /* This assumes an identical definition of serial number between BAL and MAPLE */
+ memcpy(&p_bal_util_ind_msg->data, p_serial_number, sizeof(bcmbal_serial_number));
+ }
+
+ }
+ else
+ {
+ p_bal_util_ind_msg->status = err;
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_ni),
+ "Reporting to Core: %s Indication from mac util: Failure, with status = %s, fail_reason = %d\n",
+ ((BAL_UTIL_OPER_SUB_TERM_ADD == oper) ? "BAL_UTIL_OPER_SUB_TERM_ADD" :
+ (BAL_UTIL_OPER_SUB_TERM_REMOVE == oper) ? "BAL_UTIL_OPER_SUB_TERM_REMOVE" :
+ "BAL_UTIL_OPER_SUB_TERM_DISCOVERY"),
+ bcmos_strerror(err), fail_reason);
+ }
+
+ mac_util_ind_send(p_bal_util_ind_msg);
+
+ }
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_ni),
+ "Could not allocate memory for subscriber-terminal IND message\n");
+ }
+}
+
+
+/**
+ * Notify core flow FSM that flow add/modify/remove was success or failed
+ *
+ * @param flow_key
+ * @param pon_if pon interface
+ * @param op_type ADD, REMOVE, MODIFY
+ * @param err error code to be sent up
+ *
+ **/
+static void _mac_util_report_flow_set_indication(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type, bcmos_errno err)
+{
+ bal_util_msg_ind *p_bal_util_ind_msg;
+
+ if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind))))
+ {
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "Reporting to Core: flow %d, %s %s, result=%s\n",
+ flow_key.flow_id,
+ (BCMBAL_FLOW_TYPE_UPSTREAM == flow_key.flow_type ? "upstream" :
+ BCMBAL_FLOW_TYPE_DOWNSTREAM == flow_key.flow_type ? "downstream" :
+ BCMBAL_FLOW_TYPE_MULTICAST == flow_key.flow_type ? "multicast" :"broadcast"),
+ (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW ADD":
+ (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW REMOVE" : "FLOW_CLEAR")),
+ bcmos_strerror(err));
+
+
+ /* set bal app p_msg version */
+ p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION;
+ p_bal_util_ind_msg->obj_key.flow_key = flow_key;
+ p_bal_util_ind_msg->status = err; /* set the error code */
+
+ bcmbal_msg_hdr_set(p_bal_util_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_FLOW,
+ op_type,
+ 0);
+
+
+ mac_util_ind_send(p_bal_util_ind_msg);
+ }
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "Could not allocate memory for flow IND message\n");
+ }
+}
+
+void mac_util_report_tm_sched_set_indication(bcmbal_tm_sched_key tm_sched_key, bcmos_errno err, bcmolt_result ind_result)
+{
+ bal_util_msg_ind *p_bal_util_ind_msg;
+
+ if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != ind_result))
+ {
+ err = BCM_ERR_INTERNAL;
+ }
+
+ if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind))))
+ {
+
+ BCM_LOG(INFO, log_id_mac_util, "Reporting to Core: tm sched %d, %s, result=%s\n",
+ tm_sched_key.id,
+ (BCMBAL_TM_SCHED_DIR_US == tm_sched_key.dir ? "upstream" :"downstream"),
+ bcmos_strerror(err));
+
+
+ /* set bal app p_msg version */
+ p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION;
+ p_bal_util_ind_msg->obj_key.tm_sched_key = tm_sched_key;
+ p_bal_util_ind_msg->status = err; /* set the error code */
+
+ bcmbal_msg_hdr_set(p_bal_util_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_TM_SCHED,
+ BAL_UTIL_OPER_AGG_PORT_ADD,
+ 0);
+
+
+ mac_util_ind_send(p_bal_util_ind_msg);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Could not allocate memory for tm sched IND message\n");
+ }
+}
+
+/**
+ * Notify core group FSM that group set request was success or failed
+ *
+ * @param group_key
+ * @param op_type ADD, REMOVE, SET, CREATE, DESTROY
+ * @param err error code to be sent up
+ *
+ **/
+static void _mac_util_report_group_set_indication (bcmbal_group_key group_key, bal_util_oper_group op_type, bcmos_errno err)
+{
+ bal_util_msg_ind *p_bal_util_ind_msg;
+
+ if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind))))
+ {
+
+ BCM_LOG(INFO, log_id_mac_util, "Reporting to Core: group %d, %s, result=%s\n",
+ group_key.group_id,
+ BCMBAL_UTIL_GROUP_OPER_STR_GET(op_type),
+ bcmos_strerror(err));
+
+
+ /* set bal app p_msg version */
+ p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION;
+ p_bal_util_ind_msg->obj_key.group_key = group_key;
+ p_bal_util_ind_msg->status = err; /* set the error code */
+
+ bcmbal_msg_hdr_set(p_bal_util_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ BAL_MSG_TYPE_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_GROUP,
+ op_type,
+ 0);
+
+
+ mac_util_ind_send(p_bal_util_ind_msg);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Could not allocate memory for group IND message\n");
+ }
+}
+
+/**
+ * Notify core flow FSM that flow operational state was changed
+ *
+ * @param pon_if - the flow interface
+ * @param flow_key
+ * @param op_type - relevant flow latest operation
+ * @param ind - success/fail represent current flow state is up/down
+ *
+ **/
+
+void mac_util_report_flow_auto_ind (uint32_t pon_if, bcmbal_flow_key flow_key ,bal_util_oper_flow op_type, bal_util_flow_ind ind)
+{
+ bal_util_msg_auto_ind *p_bal_util_auto_ind_msg;
+
+ if(NULL != (p_bal_util_auto_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_auto_ind) + sizeof(bcmbal_status))))
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "Reporting to Core: flow %d, %s %s, change to %s\n",
+ flow_key.flow_id,
+ (BCMBAL_FLOW_TYPE_UPSTREAM == flow_key.flow_type ? "upstream" :
+ BCMBAL_FLOW_TYPE_DOWNSTREAM == flow_key.flow_type ? "downstream" :
+ BCMBAL_FLOW_TYPE_MULTICAST == flow_key.flow_type ? "multicast" :"broadcast"),
+ (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW ADD":
+ (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW REMOVE" : "FLOW_CLEAR")),
+ ind == BAL_UTIL_FLOW_IND_SEND_FAIL ? "fail" : "success");
+
+ /* set bal app p_msg version */
+ p_bal_util_auto_ind_msg->version = BAL_UTIL_MSG_VERSION;
+ p_bal_util_auto_ind_msg->obj_key.flow_key = flow_key;
+
+ /*data will indicate the new operational state*/
+ *(p_bal_util_auto_ind_msg->data) = ((ind == BAL_UTIL_FLOW_IND_SEND_FAIL) ? BCMBAL_STATUS_DOWN : BCMBAL_STATUS_UP);
+ p_bal_util_auto_ind_msg->status = BCM_ERR_OK;
+
+ bcmbal_msg_hdr_set(p_bal_util_auto_ind_msg,
+ BCMBAL_MAC_UTIL_MSG,
+ BAL_MSG_TYPE_AUTO_IND,
+ BAL_SUBSYSTEM_MAC_UTIL,
+ BCMBAL_OBJ_ID_FLOW,
+ op_type,
+ 0);
+
+ mac_util_auto_ind_send(p_bal_util_auto_ind_msg);
+ }
+}
+
+
+/** @brief Wrapper routine to Notify core flow FSM that flow ADD Success */
+void mac_util_report_flow_add_success(bcmbal_flow_key flow_key, uint32_t pon_if)
+{
+ _mac_util_report_flow_set_indication(flow_key, pon_if, BAL_UTIL_OPER_FLOW_ADD, BCM_ERR_OK);
+}
+
+/** @brief Wrapper routine to Notify core flow FSM that flow Add failed, based on result in indication msg from Maple */
+void mac_util_report_flow_add_failed(bcmbal_flow_key flow_key, uint32_t pon_if, bcmos_errno err)
+{
+ _mac_util_report_flow_set_indication(flow_key, pon_if, BAL_UTIL_OPER_FLOW_ADD, err);
+}
+
+/** @brief Wrapper routine to Notify core flow FSM that flow REMOVE is Success */
+void mac_util_report_flow_remove_success(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type)
+{
+ _mac_util_report_flow_set_indication(flow_key, pon_if, op_type, BCM_ERR_OK);
+}
+
+/** @brief Wrapper routine to Notify core flow FSM that flow Remove failed, based on result in indication msg from Maple */
+void mac_util_report_flow_remove_failed(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type, bcmos_errno err)
+{
+ _mac_util_report_flow_set_indication(flow_key, pon_if, op_type, err);
+}
+
+/*****************************************************************************/
+/**
+ * @brief mac_util_access_terminal_info_validate
+ *
+ * This routine is used to validate all input attributes required for an acc term
+ * setting received from the core.
+ *
+ * @param p_acc_term_req the acc term request info
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_access_terminal_info_validate(const bcmbal_access_terminal_cfg *p_acc_term_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (BCMOS_TRUE != BCMBAL_CFG_PROP_IS_SET(p_acc_term_req, access_terminal, iwf_mode))
+ {
+ /*
+ * This is an error because the iwf mode is implicitly set by the core, based
+ * either on a parameter in the bal_config.txt file, or it is assigned a
+ * default value. Either way, this property must be set when this code
+ * executes.
+ */
+ rc = BCM_ERR_PARM;
+ }
+
+ return rc;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief check_send_flow_bal_ind_msg
+ * the routine checks the indication status of a specific given flow, which its entry was just updated
+ * As flows may be 'waiting' for a single of few maple gem port configuration complete indications
+ * before an indication of complete flow setup can be indicated to bal_core
+ *
+ * @note this send routine is called multiple times for the scenario multiple flows per GEM/Alloc Id.
+ *
+ * @todo this routine currently assumes just flow add. This should handle a flow Remove case too
+ *
+ * @param p_flow - flow instance pointer from mac util DB
+ * @param err - remote error in msg from Maple
+ * @param ind_result - the status(BCMOLT_RESULT_SUCCESS/BCMOLT_RESULT_FAIL) of indication from Maple
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno check_send_flow_bal_ind_msg (flow_list_entry *p_flow, bcmos_errno err, bcmolt_result ind_result)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmos_bool send_ind = BCMOS_TRUE;
+
+ /* for a ds flow, indication should be sent only if all constraints fulfilled:
+ indication was not sent yet
+ flow configuration completed - all related gem ports were configured to maple
+ all related gem ports configuration complete indication were received from device
+ */
+ if (NULL == p_flow)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "%s: NULL flow passed in: flow\n", __FUNCTION__);
+
+ return BCM_ERR_NOENT;
+ }
+ else
+ {
+ if (BCMOS_FALSE == p_flow->is_configuration_completed
+ || BCMOS_TRUE == p_flow->is_waiting_for_svc_port_active
+ || BAL_UTIL_FLOW_IND_SEND_NONE != p_flow->ind_sent)
+ {
+ send_ind = BCMOS_FALSE;
+ }
+ //else all conditions satisfied for sending an indication up to Core.
+ }
+
+ if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != ind_result))
+ {
+ err = BCM_ERR_INTERNAL;
+ }
+
+ if (BCMOS_TRUE == send_ind)
+ {
+ switch (p_flow->op_type)
+ {
+ case BAL_UTIL_OPER_FLOW_ADD:
+ if (BCM_ERR_OK != err)
+ {
+ /* report flow failed to Core; It is upto the core to cleanup the flows */
+
+ p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_FAIL;
+ mac_util_report_flow_add_failed(p_flow->bal_flow_key, p_flow->if_id, err);
+ }
+ else
+ {
+
+ p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_SUCCESS;
+ mac_util_report_flow_add_success(p_flow->bal_flow_key, p_flow->if_id);
+ }
+
+ break;
+
+ case BAL_UTIL_OPER_FLOW_REMOVE:
+ case BAL_UTIL_OPER_FLOW_CLEAR:
+ if (BCM_ERR_OK != err)
+ {
+ /* report flow failed to Core; It is upto the core to cleanup the flows */
+
+ p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_FAIL;
+ mac_util_report_flow_remove_failed(p_flow->bal_flow_key, p_flow->if_id, p_flow->op_type, err);
+ }
+ else
+ {
+
+ p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_SUCCESS;
+ mac_util_report_flow_remove_success(p_flow->bal_flow_key, p_flow->if_id, p_flow->op_type);
+ }
+
+ /* One more step for Flow Remove: remove from DB & Free the flow */
+ _mac_util_db_flow_remove (p_flow->if_id, p_flow);
+ _mac_util_db_flow_free (p_flow->if_id, p_flow);
+
+ break;
+
+ default:
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief mac_util_indication_cb
+ * this routine is the callback function that is registered by mac_util_indication_handler_register()
+ * to handle any indications coming from maple device
+ * this is the entry point for the device towards mac_util/bal
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return void
+ *
+ * @todo Note that the pon interface in Auto Indication msgs from Maple is a physical interface
+ * on a device. The PON interface that is used by Core in it's requests to MAC Util,
+ * and stored in local DBs will be logical interface.
+ * So the rule of thumb would be anything coming from Maple side, translate (device + physical Interface)
+ * to Logical interface and use for logging, internal DB access etc.
+ */
+void mac_util_indication_cb(bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ switch (p_msg->obj_type)
+ {
+ case BCMOLT_OBJ_ID_DEVICE:
+ {
+ rc = mac_util_indication_handle_for_device (device_id, p_msg);
+ }
+ break;
+
+ case BCMOLT_OBJ_ID_GPON_NI:
+ case BCMOLT_OBJ_ID_GPON_ONU:
+ case BCMOLT_OBJ_ID_GPON_ALLOC:
+ case BCMOLT_OBJ_ID_GPON_GEM_PORT:
+ {
+ rc = mac_util_handle_all_olt_ind_for_gpon (device_id, p_msg);
+ }
+ break;
+
+ case BCMOLT_OBJ_ID_XGPON_NI:
+ case BCMOLT_OBJ_ID_XGPON_ONU:
+ case BCMOLT_OBJ_ID_XGPON_ALLOC:
+ {
+ rc = mac_util_handle_all_olt_ind_for_xgpon (device_id, p_msg);
+ }
+ break;
+
+ default:
+ BCM_LOG(DEBUG, log_id_mac_util, "Unhandled message indication for obj type %d\n",
+ p_msg->obj_type);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Error handling Auto Indication from Maple for obj type %d\n", p_msg->obj_type);
+ }
+
+ return;
+}
+
+
+
+/**
+ * @brief get string for the indication object type for device
+ */
+static char *mac_util_indication_get_obj_type_str_for_device (bcmolt_obj_id obj_type)
+{
+ int i = 0;
+ for (i=0; i < BCM_SIZEOFARRAY(mac_util_device_ind_handlers); i++)
+ {
+ if (obj_type == mac_util_device_ind_handlers[i].obj_type)
+ {
+ return mac_util_device_ind_handlers[i].obj_type_str;
+ }
+ }
+
+ return "Unhandled";
+}
+
+/**
+ * @brief check if mac util should report access terminal connect event to core.
+ * event will be sent only when all devices are connected successfully
+ *
+ * @return bcmos_bool
+ */
+
+static bcmos_bool mac_util_check_acc_term_report_event (void)
+{
+
+ bcmolt_devid device_id;
+
+ BCM_TOPO_FOR_EACH_DEV(device_id)
+ {
+ if (!acc_term_connectivity.devices[device_id].is_connected)
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ return BCMOS_TRUE;
+}
+
+/**
+ * @brief Handler function for Maple auto indications for a OLT Device
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_device (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_mac_util,
+ "mac_util_indication_cb received indication obj=%d/%s group=%d subgroup=%d\n",
+ p_msg->obj_type, mac_util_indication_get_obj_type_str_for_device(p_msg->obj_type),
+ p_msg->group, p_msg->subgroup);
+
+ if (BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE == p_msg->subgroup)
+ {
+ BCM_LOG(INFO, log_id_mac_util, "Device %u is ready.\n", device_id);
+
+ acc_term_connectivity.devices[device_id].is_connected = BCMOS_TRUE;
+
+ if (mac_util_check_acc_term_report_event())
+ {
+ mac_util_report_acc_term_event(p_msg->subgroup);
+ }
+
+ if (mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_post_indication_set)
+ {
+ rc = mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_post_indication_set(device_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "%s: post indication set FAILED: rc = %s (%d)\n",
+ __FUNCTION__, bcmos_strerror(rc), rc);
+ }
+ }
+ }
+ else if (BCMOLT_DEVICE_AUTO_ID_CONNECTION_FAILURE == p_msg->subgroup)
+ {
+ BCM_LOG(INFO, log_id_mac_util, "Device %u connection failed.\n", device_id);
+ if(!acc_term_connectivity.fail_reported)
+ {
+ mac_util_report_acc_term_event(p_msg->subgroup);
+ }
+ acc_term_connectivity.fail_reported = BCMOS_TRUE;
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief Common routine to get string of indication object
+ *
+ * @param obj_type obj type to get string for
+ * @param obj_types_and_handlers obj types array
+ * @param num_obj_types num obj types
+ *
+ * @return char*
+ */
+char *_mac_util_get_obj_type_str_for_indications ( bcmolt_obj_id obj_type,
+ mac_util_ind_obj_and_handlers obj_types_and_handlers[], uint16_t num_obj_types)
+{
+ int i;
+
+ for (i = 0; i < num_obj_types; i++)
+ {
+ if (obj_type == obj_types_and_handlers[i].obj_type)
+ {
+ return obj_types_and_handlers[i].obj_type_str;
+ }
+ }
+
+ return "Unhandled";
+}
+
+
+/**
+ * @brief Common routine to register for Maple auto indications
+ *
+ * @param p_rx_cfg handler config structure
+ * @param obj_types_and_handlers obj types to subscribe
+ * @param num_obj_types num obj types
+ * @param device_id specific device id (for multiple devices support)
+ *
+ * @return bcmos_errno
+ *
+ * @todo with multiple devices in future this needs to be done on per device basis and based on epon or gpon mode
+ */
+bcmos_errno _mac_util_register_for_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg,
+ mac_util_ind_obj_and_handlers obj_types_and_handlers[], uint16_t num_obj_types,
+ bcmolt_devid device_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ int i;
+
+ for (i = 0; i < num_obj_types; i++)
+ {
+ /* set to specific auto indication object type */
+ p_rx_cfg->obj_type = obj_types_and_handlers[i].obj_type;
+ rc = bcmolt_auto_rx_cb_set(device_id, p_rx_cfg);
+ if (BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief Maple auto indication register for specific device based indications
+ *
+ * @param p_rx_cfg handler config structure
+ *@param device_id specific device id (for multiple devices support)
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_register_for_device_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id)
+{
+ return _mac_util_register_for_auto_indications (p_rx_cfg, mac_util_device_ind_handlers, BCM_SIZEOFARRAY(mac_util_device_ind_handlers),device_id);
+}
+
+
+/**
+ * @brief mac_util_indication_handler_register
+ * this local routine registers the local function 'mac_util_indication_cb'
+ * as the callback for any indications coming from maple device
+ *
+ *@param device_id specific device id (for multiple devices support)
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handler_register(bcmolt_devid device_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ struct bcmolt_rx_cfg rx_cfg =
+ {
+ .obj_type = BCMOLT_OBJECT_ANY,
+ .rx_cb = g_indication_handler,
+ .flags = BCMOLT_AUTO_FLAGS_DISPATCH,
+ .module = BCMOS_MODULE_ID_WORKER_MGMT,
+ .pon_ni_mask = 0 /** Bitmask of pon_ni interfaces the registration applies to. 0=all interfaces. */
+ };
+
+
+ rc = mac_util_register_for_device_auto_indications(&rx_cfg, device_id);
+ if (BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ rc = mac_util_register_for_gpon_auto_indications(&rx_cfg, device_id);
+ if (BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ rc = mac_util_register_for_xgpon_auto_indications(&rx_cfg, device_id);
+ if (BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief reset mac_util access terminal internal db
+ * all devices marked as disconnected
+ */
+
+static void mac_util_access_terminal_reset (void)
+{
+ bcmolt_devid device_id;
+
+ BCM_TOPO_FOR_EACH_DEV(device_id)
+ {
+ acc_term_connectivity.devices[device_id].is_connected = BCMOS_FALSE;
+ }
+
+ acc_term_connectivity.fail_reported = BCMOS_FALSE;
+}
+
+/**
+ * @brief reset a single maple device
+ *
+ * @param device_id the maple device id to be reset
+ *
+ * @return bcmos_errno
+ */
+
+static bcmos_errno reset_device(bcmolt_devid device_id)
+{
+
+ bcmolt_device_key key = {};
+ bcmolt_device_reset oper;
+
+ BCMOLT_OPER_INIT(&oper, device, reset, key);
+ BCMOLT_OPER_PROP_SET(&oper, device, reset, mode, BCMOLT_DEVICE_RESET_MODE_DEVICE);
+
+ return bcmolt_oper_submit(device_id , &oper.hdr);
+}
+
+/**
+ * @brief common config across mac modes during access terminal set.
+ * currently only the admin up case is supported (op_type is ignored))
+ * @note this is called from individual mac handler files rather than calling upfront here in this file
+ * in access_terminal_set(), because this is not to be called for loopback mode.
+ *
+ *
+ * @return bcmos_errno
+ */
+
+bcmos_errno maple_access_terminal_set_common (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+
+ rc = reset_device(device_id);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Failed to reset device %d (%s)\n", device_id, bcmos_strerror(rc));
+ return rc;
+ }
+ /* Because there is no indication coming from Maple that device reset is complete, we should sleep here. 1 second should be enough. */
+ bcmos_usleep(1000000);
+
+ /* register for maple indications - doing it after reset to avoid catching stale indications */
+ rc = mac_util_indication_handler_register(device_id);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Failed to register for device %d indications (%s)\n", device_id, bcmos_strerror(rc));
+ return rc;
+ }
+ /* using 1 second delay between the indication registration and configuration setup
+ to let the maple proxy queue get empty */
+ bcmos_usleep(1000000);
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno maple_access_terminal_connect_common (bcmolt_devid device_id)
+{
+ bcmos_errno rc;
+ bcmolt_device_connect dev_connect_oper;
+ bcmolt_device_key key = {};
+
+ /* invoking the connect operation */
+ BCMOLT_OPER_INIT(&dev_connect_oper, device, connect, key);
+
+ rc = bcmolt_oper_submit(device_id, &dev_connect_oper.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Failed to submit connect operation for device %d (%s), err_text = %s\n",
+ device_id, bcmos_strerror(rc), dev_connect_oper.hdr.hdr.err_text);
+ }
+
+ return rc;
+}
+
+/* Derive a specific device system mode from topology and store it at the internal db*/
+static bcmos_errno mac_util_system_mode_get(bcmolt_devid device_id)
+{
+ uint32_t logical_pon;
+ uint32_t pon_mode2max_physical_pons[BCM_TOPO_PON_MODE__NUM_OF] = {};
+
+ BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon)
+ {
+ uint32_t physical_pon;
+ bcm_topo_pon_mode pon_mode;
+
+ pon_mode = bcm_topo_pon_get_pon_mode(logical_pon);
+ bcm_topo_pon_get_logical2physical(logical_pon, &device_id, &physical_pon);
+ /* Get the number of physical PONs mapped.
+ * For example, if the user mapped only 4 physical PONs out of 16 in GPON mode, and the maximum physical PON mapped was 11, then the system mode should be GPONx16, not GPONx8. */
+ pon_mode2max_physical_pons[pon_mode] = MAX(pon_mode2max_physical_pons[pon_mode], physical_pon + 1);
+
+ }
+
+ if (bcmbal_is_mac_in_loopback())
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_LOOPBACK;
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_GPON])
+ {
+ if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_GPON] <= 8)
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_GPON__8_X;
+ else
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_GPON__16_X;
+ }
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_XGPON])
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_XGPON_1__8_X;
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_XGS])
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_XGS__2_X_10_G;
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_TDMA])
+ {
+ if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_TDMA] <= 4)
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA;
+ else
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA;
+ }
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_1G])
+ {
+ if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_1G] <= 4)
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__4_X;
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_1G] <= 8)
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__8_X;
+ else
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__16_X;
+ }
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_10G])
+ {
+ if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_10G] <= 2)
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__2_X_10_G;
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_10G] <= 4)
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__4_X_10_G;
+ else
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__8_X_10_G;
+ }
+ else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_LOOPBACK])
+ acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_LOOPBACK;
+ else
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Cannot determine system mode from topology\n");
+ return BCM_ERR_PARM;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief Command Set setup routine for access terminal connect to the mac devices
+ *
+ * This routine is called by acc_term_fsm in the BAL core, at an admin up operation
+ * and will result in setting and connecting all the access terminal devices
+ *
+ * @param p_acc_term Pointer to access terminal instance
+ * @param op_type Operation type on access terminal instance
+ *
+ * @return bcmos_errno
+ *
+ * @todo this code will change with multiple devices
+ */
+bcmos_errno mac_util_access_terminal_set(acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_devid device_id;
+ bcmos_bool is_wait_for_report = BCMOS_FALSE;
+
+ BCM_TOPO_FOR_EACH_DEV(device_id)
+ {
+ /*will reset and connect, in case the device is not already connected*/
+ if (!acc_term_connectivity.devices[device_id].is_connected)
+ {
+ /* Add timeout between bringing up maple devices.
+ * Otherwise, maple APIs can time out
+ */
+ if (is_wait_for_report)
+ bcmos_usleep(10000000);
+ is_wait_for_report = BCMOS_TRUE;
+ /* mac mode specific acc term set */
+ if (mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_set)
+ {
+ rc = mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_set(p_acc_term, op_type, device_id);
+ }
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "%s: FAILED: rc = %s (%d)\n",
+ __FUNCTION__, bcmos_strerror(rc), rc);
+ return rc;
+ }
+ }
+ }
+ if (!is_wait_for_report)
+ {
+ mac_util_report_acc_term_event(BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE);
+ }
+
+ return rc;
+}
+
+/*---------------------------------------------------------------------------------------------*/
+/*----------------------------------interface set handling-------------------------------------------*/
+
+/**
+ * @brief Command Set setup routine for interface up to mac application
+ *
+ * This routine is called by if_fsm in the BAL core to initialize the command
+ * set to up the interface of the mac application. The cmdset actually
+ * consists of two commands, one is to send the if up request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param op_type Operation type on interface instance
+ *
+ * @return bcmos_errno
+ *
+ * @todo system mode to identify handler function is global across olt now.
+ * This should be queried for per pon interface and used to identify the protocol
+ * and the corresponding handler.
+ */
+bcmos_errno mac_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
+{
+ /* Parameter checks */
+ BUG_ON(NULL == p_interface_inst);
+
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key;
+ bcm_topo_pon_mode pon_mode;
+
+ /* First check if it is for PON interface. If not (i.e. NNI), then just return a success without
+ * forwarding anything to MAC hardware.
+ */
+ if (BCMBAL_INTF_TYPE_PON != intf_key.intf_type)
+ {
+ mac_util_report_if_event(intf_key.intf_id,
+ intf_key.intf_type,
+ BCM_ERR_OK, BCMOLT_RESULT_SUCCESS,
+ ((BAL_UTIL_OPER_IF_UP == op_type) ? BCMOLT_PON_STATE_ACTIVE_WORKING : BCMOLT_PON_STATE_INACTIVE));
+
+ return BCM_ERR_OK;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "SET if %s , intf_type: %s, intf_id: %d\n",
+ (BAL_UTIL_OPER_IF_UP == op_type ? "UP" : "DOWN"),
+ (BCMBAL_INTF_TYPE_PON == intf_key.intf_type ? "PON":"NNI"),
+ intf_key.intf_id);
+
+ /* query PON mode */
+ pon_mode = mac_util_get_pon_mode(intf_key.intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ rc = BCM_ERR_INTERNAL;
+
+ /* system mode specific interface set */
+ if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].if_set)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].if_set(p_interface_inst, op_type);
+ }
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed INTERFACE-%s operation for IF %d\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "UP" : "DOWN", intf_key.intf_id);
+ }
+
+ return rc;
+}
+
+
+
+/*****************************************************************************/
+/**
+ * @brief mac_util_subscriber_terminal_info_validate
+ *
+ * This routine is used to validate all input attributes required for a sub term setting
+ * received from core
+ *
+ * @param p_sub_term_req A pointer to a subscriber terminal object
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_subscriber_terminal_info_validate(const bcmbal_subscriber_terminal_cfg *p_sub_term_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_sub_term_req->key.intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ rc = BCM_ERR_INTERNAL;
+
+ /* validate system mode specific things */
+ if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_validate)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_validate(p_sub_term_req);
+ }
+
+ return rc;
+}
+
+
+/*----------------------------------subscriber terminal set handling-----------------------------------*/
+
+/**
+ * @brief Command Set setup routine for subscriber terminal connect to mac application
+ *
+ * This routine is called by sub_term_fsm in the BAL core to initialize the command
+ * set to connect the subscriber terminal of the mac application. The cmdset actually
+ * consists of two commands, one is to send the sub_term request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_sub_term_inst A pointer to a subscriber terminal instance
+ * @param op_type Type of operation being performed on the subscriber terminal instance
+ * @param is_post_discovery Used for ADD, indicates if this request is after a ONU Discovery
+ *
+ * @return bcmos_errno
+ */
+
+bcmos_errno mac_util_subscriber_terminal_set(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
+ bcm_topo_pon_mode pon_mode;
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "IN : %s pon_id = %d onu_id= %d "
+ "omci_gem_port = %d\n",
+ __FUNCTION__,
+ p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id, p_sub_term_req->data.svc_port_id);
+
+ if ((BAL_UTIL_OPER_SUB_TERM_ADD != op_type)
+ && (BAL_UTIL_OPER_SUB_TERM_REMOVE != op_type)
+ && (BAL_UTIL_OPER_SUB_TERM_CLEAR != op_type))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Unsupported operation %d for sub_term %u\n",
+ op_type, p_sub_term_req->key.sub_term_id);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_sub_term_req->key.intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ rc = BCM_ERR_INTERNAL;
+
+ /* system mode specific sub term set */
+ if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_set)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_set(p_sub_term_inst, op_type, is_post_discovery);
+ }
+
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s: Failed: rc = %s (%d)\n",
+ __FUNCTION__, bcmos_strerror(rc), rc);
+ }
+
+ return rc;
+}
+
+
+
+
+/*---------------------------------------------------------------------------------------------*/
+/*------------------group set handling GROUP routines and helper functions-------------------*/
+/*---------------------------------------------------------------------------------------------*/
+
+/*****************************************************************************/
+/**
+ * @brief mac_util_group_info_validate
+ *
+ * This routine is used to validate all input attributes required for a group
+ * setting received from core
+ *
+ * @param p_group_req A pointer to a group object
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_group_info_validate(const bcmbal_group_cfg *p_group_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ int i;
+
+ do
+ {
+ /* if the group has no owner, no need to check as service port will not be assigned */
+ if (p_group_req->data.owner == BCMBAL_GROUP_OWNER_NONE)
+ {
+ break;
+ }
+ /* if group member command is set, there has to be member info,
+ for remove, service port is an option
+ */
+ if (BCMBAL_CFG_PROP_IS_SET(p_group_req, group, members_cmd))
+ {
+ if(p_group_req->data.members.len)
+ {
+ for(i=0; i< p_group_req->data.members.len; i++)
+ {
+ /* all members should have the service port as non-zero */
+ if (!p_group_req->data.members.val[i].svc_port_id)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "svc_port_id is a mandatory parameter for a group member, and it can not set to zero\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ break;
+ }
+ }
+ }
+ }
+
+ }while(0);
+
+ return rc;
+}
+
+/**
+ * @brief Core interface: setup routine for group
+ *
+ * This routine is called by group_fsm in the BAL core to
+ * add/remove/set group in the mac application. Unlike flow request,
+ * the mac driver does not send indication messages back upon completion.
+ * This routine needs to fake an indication message to core to trigger the group_fsm.
+ *
+ * @param p_grp_inst Pointer to group instance
+ * @param op_type Operation type on group instance
+ * @param send_ind TRUE - send indication, FALSE - don't send indication
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_group_set(group_inst *p_grp_inst, bal_util_oper_group op_type, bcmos_bool send_ind)
+{
+ bcmbal_group_cfg *p_group_req = &p_grp_inst->api_req_group_info;
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmbal_group_cfg *p_group_lookup_info = NULL;
+ bcm_topo_pon_mode pon_mode;
+
+ do
+ {
+ /* if the group has no owner, no need to access the HW as service port will not be set */
+ if (p_group_req->data.owner == BCMBAL_GROUP_OWNER_NONE)
+ {
+ break;
+ }
+
+ /*
+ * When we are doing a GROUP_ADD, the API request has the information we need,
+ * When we are doing a GROUP_DESTROY, the current group info has this information (because
+ * the GROUP_DESTROY request only has the group key populated. The current flow info has
+ * all of the attributes used when create the group.
+ */
+ p_group_lookup_info = (BAL_UTIL_OPER_GROUP_DESTROY == op_type) ? &p_grp_inst->current_group_info : p_group_req;
+
+ BCM_LOG(INFO, log_id_mac_util, "%s group_id = %d with oper type %s\n ",
+ __FUNCTION__,
+ p_group_lookup_info->key.group_id,
+ BCMBAL_UTIL_GROUP_OPER_STR_GET(op_type)
+ );
+
+ /* mac only need to response to set member when op_type is ADD/REMOVE/SET - configure multicast service ports */
+ if ((BAL_UTIL_OPER_GROUP_ADD == op_type ||
+ BAL_UTIL_OPER_GROUP_REMOVE == op_type ||
+ BAL_UTIL_OPER_GROUP_SET == op_type ) &&
+ BCMBAL_CFG_PROP_IS_SET(p_group_req, group, members))
+ {
+ /* assume all members are of same mode */
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_group_req->data.members.val[0].intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ {
+ rc = BCM_ERR_INTERNAL;
+ }
+ /* system mode specific group set */
+ else if ( mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set(p_group_req, op_type, p_grp_inst);
+ }
+
+ }
+
+ /* special case - destroy with valid members, then need to remove all members */
+ else if ((BAL_UTIL_OPER_GROUP_DESTROY == op_type && p_group_lookup_info->data.members.len != 0))
+ {
+ /* query system mode - use first member as default */
+ pon_mode = mac_util_get_pon_mode(p_group_lookup_info->data.members.val[0].intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ {
+ rc = BCM_ERR_INTERNAL;
+ }
+ /* system mode specific group set */
+ else if ( mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set(p_group_lookup_info, BAL_UTIL_OPER_GROUP_REMOVE, p_grp_inst);
+ }
+ }
+ }while(0);
+
+ /* return an indication message to core */
+ if(send_ind)
+ {
+ _mac_util_report_group_set_indication(p_group_req->key, op_type, rc);
+ }
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "%s Failed: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+
+ return rc;
+}
+
+
+/*---------------------------------------------------------------------------------------------*/
+/*------------------flow set handling Interface routines and helper functions-------------------*/
+/*---------------------------------------------------------------------------------------------*/
+
+
+
+/*****************************************************************************/
+/**
+ * @brief mac_util_flow_info_validate
+ *
+ * This routine is used to validate all input attributes required for a flow
+ * setting received from core
+ *
+ * @param p_flow_req A pointer to a flow object
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_flow_info_validate(const bcmbal_flow_cfg *p_flow_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+
+ do
+ {
+ if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_MULTICAST)
+ {
+ /* nothing to do in multicast FLOW - validate in GROUP*/
+ break;
+ }
+ if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM &&
+ BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, group_id) )
+ {
+ /* nothing to do in DS N:1 FLOW - validate in GROUP */
+ break;
+ }
+
+ if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, access_int_id))
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "access if id is a mandatory parameter for a flow, and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+
+ break; /* if interface id not set then skip rest of the checks */
+ }
+
+ if (p_flow_req->key.flow_type != BCMBAL_FLOW_TYPE_BROADCAST)
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, sub_term_id))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "sub term id is a mandatory parameter for a flow, and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+ }
+
+ if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, svc_port_id))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "svc_port_id is a mandatory parameter for a flow, and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+
+ /* validate flow id */
+ if (BCMOS_FALSE == MAC_UTIL_FLOW_DB_FLOW_ID_IS_VALID(p_flow_req->key.flow_id))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "flow Id from user is not within range: %d <= flow id <= %d\n",
+ MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL);
+ rc = BCM_ERR_PARM;
+ }
+
+
+
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_flow_req->data.access_int_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ {
+ rc = BCM_ERR_INTERNAL;
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "could not get system mode for pon interface\n");
+ }
+ }
+
+ /* system mode specific validation */
+ if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_validate)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_validate(p_flow_req);
+ /* the called function will log any protocol specific validation errors */
+ }
+
+ } while (0);
+
+ return rc;
+}
+
+/**
+ * @brief Core interface: setup routine for flow
+ *
+ * This routine is called by flow_fsm in the BAL core to initialize the command
+ * to add flow to the mac application. The cmdset actually
+ * consists of two commands, one is to send the flow request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_flow_core Pointer to flow instance from core fsm
+ * @param op_type Operation type on flow instance
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_flow_set(flow_inst *p_flow_core, bal_util_oper_flow op_type)
+{
+ bcmbal_flow_cfg *p_flow_req = &p_flow_core->api_req_flow_info;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmbal_flow_cfg *p_flow_lookup_info = NULL;
+ bcm_topo_pon_mode pon_mode;
+
+ /*
+ * When we are doing a FLOW_ADD, the API request has the information we need,
+ * When we are doing a FLOW_REMOVE, the current flow info has this information (because
+ * the FLOW_REMOVE request only has the flow key populated. The current flow info has
+ * all of the attributes used to create the flow in the first place.
+ */
+ p_flow_lookup_info = (BAL_UTIL_OPER_FLOW_ADD == op_type) ? p_flow_req : &p_flow_core->current_flow_info;
+
+ bcmos_bool flow_is_destined_to_host = BAL_UTIL_OPER_FLOW_ADD == op_type ?
+
+ ((BCMBAL_CFG_PROP_IS_SET(&p_flow_core->api_req_flow_info, flow, action) &&
+ (p_flow_core->api_req_flow_info.data.action.cmds_bitmask &
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE) :
+
+ ((BCMBAL_CFG_PROP_IS_SET(&p_flow_core->current_flow_info, flow, action) &&
+ (p_flow_core->current_flow_info.data.action.cmds_bitmask &
+ BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE);
+
+ /* There's no need to do anything with the MAC in downstream flows that
+ * that are destined to the host CPU (i.e. NNI->CPU)
+ */
+ if(((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type) &&
+ flow_is_destined_to_host))
+ {
+ /* When the flow is downstream and destined to the host (i.e. NNI->CPU), then there
+ * is nothing to do in the MAC, so just return an indication to allow the FSM to continue on.
+ */
+ if (BAL_UTIL_OPER_FLOW_ADD == op_type)
+ {
+ mac_util_report_flow_add_success(p_flow_req->key, p_flow_req->data.access_int_id);
+ }
+ else if ((BAL_UTIL_OPER_FLOW_REMOVE == op_type) || (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
+ {
+ mac_util_report_flow_remove_success(p_flow_req->key, p_flow_req->data.access_int_id, op_type);
+ }
+ }
+ /* for multicast flow all works are done in GROUP object, simply send the indication to Core */
+ else if (BCMBAL_FLOW_TYPE_MULTICAST == p_flow_req->key.flow_type)
+ {
+ /* there is no access_int_id for multicast flow, pass 0 as parameter.
+ The interface number is just used for logging purpose in the indication API */
+ _mac_util_report_flow_set_indication(p_flow_req->key, 0, op_type, rc);
+ }
+ /* for downstream n:1 flow all works are done in GROUP object, simply send the indication to Core */
+ else if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type &&
+ (BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, group_id)) )
+ {
+ /* there is no access_int_id for DS N:1 flow, pass 0 as parameter.
+ The interface number is just used for logging purpose in the indication API */
+ _mac_util_report_flow_set_indication(p_flow_req->key, 0, op_type, rc);
+ }
+ else
+ {
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "%s flow_id = %d dir = %s, pon_id = %d "
+ "onu_id= %d alloc_id = %d gem_port = %d, op_type = %s\n",
+ __FUNCTION__,
+ p_flow_lookup_info->key.flow_id,
+ p_flow_lookup_info->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ? "up":"down",
+ p_flow_lookup_info->data.access_int_id,
+ p_flow_lookup_info->data.sub_term_id,
+ p_flow_lookup_info->data.agg_port_id,
+ p_flow_lookup_info->data.svc_port_id,
+ (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW_ADD":
+ (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW_REMOVE" : "FLOW_CLEAR")));
+
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_flow_req->data.access_int_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ rc = BCM_ERR_INTERNAL;
+
+ /* system mode specific flow set */
+ if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_set)
+ {
+ rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_set(p_flow_lookup_info, op_type, p_flow_core);
+ }
+ }
+
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "%s Failed: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+
+ return rc;
+}
+
+/*****************************************************************************/
+/**
+ * @brief mac_util_tm sched_info_validate
+ *
+ * This routine is used to validate all input attributes required for a tm sched
+ * setting received from core
+ *
+ * @param p_tm_sched_req A pointer to a tm sched object
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_tm_sched_info_validate(const bcmbal_tm_sched_cfg *p_tm_sched_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+ do
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_req, tm_sched, owner))
+ {
+ /* nothing to do in MAC */
+ break;
+ }
+
+ if (p_tm_sched_req->data.owner.type != BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT)
+ {
+ /* nothing to do in MAC */
+ break;
+ }
+
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_tm_sched_req->data.owner.u.agg_port.intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ rc = BCM_ERR_INTERNAL;
+
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_tm_sched_req->data.owner.u.agg_port.intf_id),
+ "could not get system mode for pon interface\n");
+ }
+ } while (0);
+ return rc;
+}
+
+bcmos_errno mac_util_agg_port_set(tm_sched_inst *p_tm_sched, bal_util_oper_agg_port op_type)
+{
+ bcmbal_tm_sched_cfg *p_agg_port_req = &p_tm_sched->req_tm_sched_info;
+ bcmos_errno rc = BCM_ERR_OK;
+
+
+ bcm_topo_pon_mode pon_mode;
+ do
+ {
+
+ /* query system mode */
+ pon_mode = mac_util_get_pon_mode(p_agg_port_req->data.owner.u.agg_port.intf_id);
+ if (pon_mode == BCM_TOPO_PON_MODE_INVALID)
+ {
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ rc = maple_mac_util_agg_port_set(p_agg_port_req, op_type, p_tm_sched);
+
+ }while(0);
+ return rc;
+}
+
+#if !defined(WRX_BUILD)
+/* Internal function that finds UDP port to bind to */
+static bcmos_errno _mac_util_find_free_udp_port(uint16_t *p_port)
+{
+#define MAX_UDP_PORT_TRY_ITER 100 /* Try 100 times, then give up */
+#define MAX_UDP_PORT 60000
+#define MIN_UDP_PORT (MAX_UDP_PORT / 2)
+ uint16_t port;
+ struct sockaddr_in sa;
+ int sock;
+ int bind_rc;
+ int i = 0;
+
+ /* Open UDP socket */
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't create UDP socket. error %s\n", strerror(errno));
+ }
+
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = INADDR_ANY;
+
+ do
+ {
+ port = rand() % MAX_UDP_PORT;
+ if (port < MIN_UDP_PORT)
+ port += MIN_UDP_PORT;
+ sa.sin_port = htons(port);
+ bind_rc = bind(sock, (struct sockaddr *)&sa, sizeof(sa));
+ } while (bind_rc < 0 && ++i < MAX_UDP_PORT_TRY_ITER);
+
+ /* Yes, yes. There is a possible race condition that someone will take the port we've just found
+ * before we had a chance to bind it again.
+ * In this unlikely case BAL application will fail on startup and will have to be restarted.
+ */
+ close(sock);
+
+ if (bind_rc < 0)
+ {
+ BCMOS_TRACE_RETURN(BCM_ERR_NORES, "Couldn't find unused UDP port after %d tries. Giving up.\n", i);
+ }
+
+ *p_port = port;
+
+ return BCM_ERR_OK;
+}
+#endif
+
+static void bal_indication_cb(bcmolt_devid olt, bcmolt_msg *p_msg)
+{
+ mac_util_indication_cb(olt, p_msg);
+
+ bcmolt_msg_free(p_msg);
+}
+
+#ifdef ENABLE_LOG
+/**
+ * @brief routine to register per pon log strings with logger
+ *
+ * @param system_mode -OLT system mode
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_register_logging_per_pon (void)
+{
+ char log_str_buf[MAC_UTIL_LOG_STR_SZ] = {0};
+ bcmolt_devid device_id;
+ uint32_t logical_pon;
+
+ /** @note if by any chance the system mode is set multiple times, then we want to avoid
+ * re-registering already registered pon interfaces, because there is currently no way
+ * to de-register those interfaces first. We will just register the not-registered ones.
+ */
+ /* register log Ids for each PON interface, that is not already registered */
+ BCM_TOPO_FOR_EACH_PON(device_id, logical_pon)
+ {
+ if (0 != log_id_mac_util_pon_if[logical_pon])
+ {
+ continue;
+ }
+
+ /* make a log id string */
+ MAC_UTIL_MAKE_LOG_STR_FOR_PON_IF(logical_pon, log_str_buf, sizeof(log_str_buf));
+ /* register log id string for pon interface */
+ log_id_mac_util_pon_if[logical_pon] = bcm_dev_log_id_register(log_str_buf, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_mac_util_pon_if[logical_pon] == DEV_LOG_INVALID_ID);
+ }
+
+ return BCM_ERR_OK;
+}
+#endif
+
+
+
+/**
+ * @brief get ip & port for MAC/Maple
+ */
+bcmos_errno mac_util_init_parse_mac_ip_and_port (const char *maple_address)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+#if !defined(WRX_BUILD)
+ rc = app_util_parse_ip_port(maple_address, &bcmtr_olt_ip[0], &bcmtr_olt_udp_port[0]);
+ if (rc)
+ {
+ return rc;
+ }
+
+ srand(bcmos_timestamp());
+ rc = _mac_util_find_free_udp_port(&bcmtr_host_udp_port);
+#endif
+
+ return rc;
+}
+
+
+/**
+ * @brief mac_util_init routine for mac application
+ * @param maple_address - pointer to maple device instance
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_init(const char *maple_address)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_devid device_id;
+
+ do
+ {
+#ifdef ENABLE_LOG
+ /* register a generic MAC util log Id too, for use other than PON If related logs */
+ log_id_mac_util = bcm_dev_log_id_register("MAC_UTIL", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_mac_util == DEV_LOG_INVALID_ID);
+#endif
+
+ if (!bcmbal_is_mac_in_loopback())
+ {
+ rc = mac_util_init_parse_mac_ip_and_port (maple_address);
+ if (BCM_ERR_OK != rc)
+ break;
+ }
+
+ g_indication_handler = bal_indication_cb;
+
+ BCM_TOPO_FOR_EACH_DEV(device_id)
+ {
+ rc = mac_util_system_mode_get(device_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "%s: system mode get for device %d FAILED: rc = %s (%d)\n",
+ __FUNCTION__, device_id, bcmos_strerror(rc), rc);
+ break;
+ }
+ }
+
+#ifdef ENABLE_LOG
+ /* register logging for each PON based on mac mode*/
+ mac_util_register_logging_per_pon();
+#endif
+
+ mac_util_access_terminal_reset();
+
+ } while(0);
+
+ return rc;
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief This function is the helper for the mac app print_flows CLI command backend
+ * which print the full internal flows list
+ *
+ * @param sess Pointer to the current cli session
+ * @param parm An array of parameters from the CLI command, which will be empty on that no parameters command case
+ * @param nParms The number of elements in the parm array (above) that have
+ * valid data, which will be 0 on that case.
+ *
+ * @returns BCM_ERR_OK on success, other bcmos_errno codes otherwise
+ *
+ *****************************************************************************/
+static bcmos_errno _cmd_flows_print(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ flow_list_entry *p_current_entry = NULL;
+ flow_list_entry *p_next_entry = NULL;
+ uint32_t if_id = 0;
+
+ printf("Flow DB: starting flow id=%d, max flow id=%d\n",
+ MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL);
+
+ for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++)
+ {
+ /* before every db segment, NULL the current entry */
+ p_current_entry = NULL;
+ p_next_entry = NULL;
+
+ /* get first */
+ p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry);
+ while (NULL != p_current_entry)
+ {
+ printf("\n------------------------------\n");
+ printf ("\nflow_id = %d flow_type = %d\n", p_current_entry->bal_flow_key.flow_id, p_current_entry->bal_flow_key.flow_type);
+ printf ("\n if_id = %d sub_term_id = %d svc_port_id = %d agg_id = %d vlan_id = %d\n",
+ p_current_entry->if_id, p_current_entry->sub_term_id, p_current_entry->svc_port_id, p_current_entry->agg_id, p_current_entry->vlan_id);
+ printf("\n is_waiting_for_svc_port_active = %s is_configuration_completed=%s ind_sent = %d\n",
+ p_current_entry->is_waiting_for_svc_port_active==BCMOS_TRUE ? "true" : "false",
+ p_current_entry->is_configuration_completed==BCMOS_TRUE ? "true" : "false",
+ p_current_entry->ind_sent);
+ printf("\n------------------------------\n");
+
+ /* get next */
+ p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry);
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno _cmd_flows_print_for_gem(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ flow_list_entry *p_current_entry = NULL;
+ void *p_rsc_mgr_curr_entry = NULL;
+ void *p_rsc_mgr_next_entry = NULL;
+
+ uint32_t if_id = 0;
+
+ printf("Flow DB for a GEM port [%ld]: starting flow id=%d, max flow id=%d\n",
+ parm[0].value.unumber, MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL);
+
+ for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++)
+ {
+ /* before every db segment, NULL the current entry */
+ p_current_entry = NULL;
+
+ /* get first */
+ p_current_entry = _mac_util_db_flow_get_next_w_gem (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ while (NULL != p_current_entry)
+ {
+ printf("\n------------------------------\n");
+ printf ("\nflow_id = %d flow_type = %d\n", p_current_entry->bal_flow_key.flow_id, p_current_entry->bal_flow_key.flow_type);
+ printf ("\n if_id = %d sub_term_id = %d svc_port_id = %d agg_id = %d vlan_id = %d\n",
+ p_current_entry->if_id, p_current_entry->sub_term_id, p_current_entry->svc_port_id, p_current_entry->agg_id, p_current_entry->vlan_id);
+ printf("\n is_waiting_for_svc_port_active = %s is_configuration_completed=%s ind_sent = %d\n",
+ p_current_entry->is_waiting_for_svc_port_active==BCMOS_TRUE ? "true" : "false",
+ p_current_entry->is_configuration_completed==BCMOS_TRUE ? "true" : "false",
+ p_current_entry->ind_sent);
+ printf("\n------------------------------\n");
+
+ /* get next */
+ p_current_entry = _mac_util_db_flow_get_next_w_gem (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+static bcmos_errno _cmd_flows_print_for_alloc_id(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ flow_list_entry *p_current_entry = NULL;
+ void *p_rsc_mgr_curr_entry = NULL;
+ void *p_rsc_mgr_next_entry = NULL;
+
+ uint32_t if_id = 0;
+
+ printf("Flow DB for a Alloc Id [%ld]: starting flow id=%d, max flow id=%d\n",
+ parm[0].value.unumber, MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL);
+
+ for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++)
+ {
+ /* before every db segment, NULL the current entry */
+ p_current_entry = NULL;
+
+ /* get first */
+ p_current_entry = _mac_util_db_flow_get_next_w_alloc_id (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ while (NULL != p_current_entry)
+ {
+ printf("\n------------------------------\n");
+ printf ("\nflow_id = %d flow_type = %d\n", p_current_entry->bal_flow_key.flow_id, p_current_entry->bal_flow_key.flow_type);
+ printf ("\n if_id = %d sub_term_id = %d svc_port_id = %d agg_id = %d vlan_id = %d\n",
+ p_current_entry->if_id, p_current_entry->sub_term_id, p_current_entry->svc_port_id, p_current_entry->agg_id, p_current_entry->vlan_id);
+ printf("\n is_waiting_for_svc_port_active = %s is_configuration_completed=%s ind_sent = %d\n",
+ p_current_entry->is_waiting_for_svc_port_active==BCMOS_TRUE ? "true" : "false",
+ p_current_entry->is_configuration_completed==BCMOS_TRUE ? "true" : "false",
+ p_current_entry->ind_sent);
+ printf("\n------------------------------\n");
+
+ /* get next */
+ p_current_entry = _mac_util_db_flow_get_next_w_alloc_id (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/* Update CLI based on the system mode */
+static void handle_system_mode_change(bcmolt_devid dev)
+{
+ if (dev == current_device)
+ {
+ bcmcli_entry *cur_dir = bcmcli_dir_get(current_session);
+ char old_dir_name[32] = "";
+
+ if (cur_dir)
+ strncpy(old_dir_name, bcmcli_token_name(cur_dir), sizeof(old_dir_name) - 1);
+
+ bcmcli_dir_set(current_session, maple_dir);
+ api_cli_set_commands(current_session);
+
+ /* Restore current CLI directory */
+ cur_dir = bcmcli_dir_find(NULL, old_dir_name);
+ bcmcli_dir_set(current_session, cur_dir);
+ }
+}
+
+
+/*****************************************************************************/
+/**
+ * @brief mac_util_cli_init
+ *
+ * This routine is called from main to initialize the mac_app cli,
+ *that is used for internal unit testing.
+ *
+ * @param cli_dir - a pointer to the cli directory to init that cli in
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_cli_init(bcmcli_entry *cli_dir)
+{
+ bcmcli_entry *p_cli_dir;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ do
+ {
+ p_cli_dir = bcmcli_dir_add(cli_dir, "Mac_Util", "Mac Util (debug)", BCMCLI_ACCESS_ADMIN, NULL);
+
+ BCMCLI_MAKE_CMD_NOPARM(p_cli_dir, "print_flows", "print mac app flows list", _cmd_flows_print);
+ BCMCLI_MAKE_CMD(p_cli_dir, "print_flows_for_gem", "print mac flows sharing a GEM port", _cmd_flows_print_for_gem,
+ BCMCLI_MAKE_PARM("gem_port_id", "GEM Port Id", BCMCLI_PARM_UNUMBER, 0));
+ BCMCLI_MAKE_CMD(p_cli_dir, "print_flows_for_alloc_id", "print mac flows sharing an Alloc Id", _cmd_flows_print_for_alloc_id,
+ BCMCLI_MAKE_PARM("alloc_id", "Alloc Id", BCMCLI_PARM_UNUMBER, 0));
+
+ /* Initialize the bal api cli UI */
+ maple_dir = bcmcli_dir_add(NULL, "maple", "Maple API access", BCMCLI_ACCESS_ADMIN, NULL);
+
+ sm_change_cb = handle_system_mode_change;
+
+ /* Init device selector */
+ rc = bcmolt_dev_sel_init(maple_dir);
+
+ /* Add Maple API commands */
+ rc = rc ? rc : api_cli_init(maple_dir, current_session);
+
+#ifdef BOARD
+ rc = rc ? rc : bcm_board_init();
+ rc = rc ? rc : bcm_board_cli_init(NULL);
+#endif
+ rc = rc ? rc : bcmtr_init();
+ rc = rc ? rc : bcmtr_cld_cli_init();
+ rc = rc ? rc : bcmtr_cli_init();
+
+ } while(0);
+
+ return rc;
+
+ return BCM_ERR_OK;
+}
+
+/*****************************************************************************/
+/**
+ * @brief Un-initialize the mac util internal data structures
+ *
+ * @returns bcmos_errno == BCM_ERR_OK
+ *
+ * @note this routine does not seem to be used currently
+ *****************************************************************************/
+bcmos_errno mac_util_finish(void)
+{
+ flow_list_entry *p_current_entry = NULL, *p_next_entry = NULL;
+ uint32_t if_id = 0;
+
+ for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++)
+ {
+ /* before every db segment, NULL the current entry */
+ p_current_entry = NULL;
+ p_next_entry = NULL;
+
+ /* Free all the entries on the flows list */
+ /* get first */
+ p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry);
+ while (NULL != p_current_entry)
+ {
+ /* Remove it from the list, and free memory */
+ _mac_util_db_flow_remove (if_id, p_current_entry);
+ _mac_util_db_flow_free (if_id, p_current_entry);
+
+ /* get next */
+ p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry);
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+bcmos_errno mac_util_access_terminal_sw_version_validate(bcmolt_devid device)
+{
+ bcmolt_device_cfg cfg = {};
+ bcmolt_device_key key = {};
+ bcmos_errno rc;
+
+ BCMOLT_CFG_INIT(&cfg, device, key);
+ BCMOLT_CFG_PROP_GET(&cfg, device, host_sw_version);
+ rc = bcmolt_cfg_get(device, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Unable to get OLT SW version\n");
+ return rc;
+ }
+
+ BCM_LOG(INFO, log_id_mac_util,
+ "Actual OLT SW version %d.%d.%X (Object model revision %d)\n",
+ cfg.data.host_sw_version.major,
+ cfg.data.host_sw_version.minor,
+ cfg.data.host_sw_version.revision,
+ cfg.data.host_sw_version.model);
+
+ BCM_LOG(INFO, log_id_mac_util,
+ "BAL OLT SW version %d.%d.%X (Object model revision %d)\n",
+ BCMOLT_HOST_MAJOR_VER,
+ BCMOLT_HOST_MINOR_VER,
+ BCMOLT_HOST_REVISION_VER,
+ BCMOLT_MODEL_REVISION);
+
+ /* Check for versions mismatch */
+ if (cfg.data.host_sw_version.major != BCMOLT_HOST_MAJOR_VER ||
+ cfg.data.host_sw_version.minor != BCMOLT_HOST_MINOR_VER ||
+ cfg.data.host_sw_version.revision != BCMOLT_HOST_REVISION_VER ||
+ cfg.data.host_sw_version.model != BCMOLT_MODEL_REVISION)
+ {
+ BCM_LOG(ERROR, log_id_mac_util, INBOLD_BAD(
+ "SW versions mismatch: BAL was complied with OTL SW version %d.%d.%X (Object model revision %d), "
+ "while actual OLT SW version is %d.%d.%X (Object model revision %d)\n"),
+ BCMOLT_HOST_MAJOR_VER,
+ BCMOLT_HOST_MINOR_VER,
+ BCMOLT_HOST_REVISION_VER,
+ BCMOLT_MODEL_REVISION,
+ cfg.data.host_sw_version.major,
+ cfg.data.host_sw_version.minor,
+ cfg.data.host_sw_version.revision,
+ cfg.data.host_sw_version.model);
+ return BCM_ERR_STATE;
+ }
+ return BCM_ERR_OK;
+}
+
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util.h b/bal_release/src/core/util/mac/bal_mac_util.h
new file mode 100755
index 0000000..e0bf5b9
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util.h
@@ -0,0 +1,295 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util.h
+ *
+ * @brief Mac util interfaces header file
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @defgroup mac_util Mac Util
+ * @ingroup core
+ */
+
+#ifndef BAL_MAC_UTIL_H
+#define BAL_MAC_UTIL_H
+
+/****************************************/
+
+#include <bcmolt_host_api.h>
+#include <acc_term_fsm.h>
+#include <sub_term_fsm.h>
+#include <flow_fsm.h>
+#include <group_fsm.h>
+#include <tm_sched_fsm.h>
+#include <bal_utils_msg.h>
+
+#include <bal_common.h>
+#include <bal_mac_util.h>
+#include <rsc_mgr.h>
+#include <bal_app_common_utils.h>
+#include <bal_utils.h>
+#include <bal_worker.h>
+#include <bal_msg.h>
+#include <bcm_topo.h>
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+#include <bcmtr_debug_cli.h>
+#endif //ENABLE_LOG
+
+
+/*@{*/
+
+/** @brief none fail reason for sub term deactivation. Defined locally, since Maple SDK does not define this. */
+#define MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE BCMOLT_ACTIVATION_FAIL_REASON_NONE
+
+/**
+ * @brief The following macros define the max and min user flow Id values and the check for a valid flow Id.
+ */
+extern uint32_t mac_util_flow_id_start_val;
+#define MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL (mac_util_flow_id_start_val)
+#define MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL (MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL+BAL_ACC_TERM_MAX_FLOWS-1)
+
+#define MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL_CONFIG(_start_val) (mac_util_flow_id_start_val = (_start_val))
+
+#define MAC_UTIL_FLOW_DB_FLOW_ID_IS_VALID(_flow_id) \
+ (((_flow_id) >= MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL) && \
+ ((_flow_id) <= MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL))
+
+typedef struct mac_util_sla mac_util_sla;
+struct mac_util_sla
+{
+ uint64_t min_rate; /* min_rate (this is a uint64_t as the units are bytes per second) */
+ uint64_t max_rate; /* max_rate (this is a uint64_t as the units are bytes per second) */
+};
+
+/* flow entry structure */
+typedef struct flow_list_entry flow_list_entry;
+struct flow_list_entry
+{
+ TAILQ_ENTRY(flow_list_entry) next;
+ bcmbal_flow_key bal_flow_key; /* bal flow key */
+ uint32_t if_id; /* pon_ni id */
+ uint32_t sub_term_id; /* onu_id */
+ uint16_t svc_port_id; /* the flow related gem port id */
+ uint16_t agg_id; /* the flow related alloc-id */
+ uint16_t vlan_id;
+ bcmos_bool is_waiting_for_svc_port_active; /* indicates whether waiting for a gem port to become active */
+ bcmos_bool is_configuration_completed;
+ bal_util_flow_ind ind_sent; /* indicates whether an indication was sent to core none/success/fail */
+ mac_util_sla sla; /* it saves a converted value for the SLAs; we may retain this in mac util */
+ bal_util_oper_flow op_type; /* Operation type: FLOW_ADD or FLOW_REMOVE */
+};
+
+#define RSRC_MGR_KEEPS_FLOW_LIST_PER_GEM BCMOS_FALSE
+
+extern dev_log_id log_id_mac_util;
+extern dev_log_id log_id_mac_util_pon_if[];
+/** @def get log Id for pon interface */
+#define MAC_UTIL_GET_LOG_ID_FOR_PON_IF(_pon_if_id) (log_id_mac_util_pon_if[(_pon_if_id)])
+
+
+/** @def system default transceiver type */
+#define BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_GPON BCMBAL_TRX_TYPE_GPON_LTE_3680_M
+#define BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_XGPON BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC
+#define BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_XGS BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC
+
+
+/**
+ * @brief is valid pon interface id
+ * @todo see if it is feasible to tie it up with system mode. However
+ * keep in mind that this check would be called for every db api call.
+ */
+#define IS_VALID_PON_IF(_pon_if) (NUM_SUPPORTED_SUBSCRIBER_INTERFACES > (_pon_if))
+
+
+/* Function Prototypes for external */
+bcmos_errno mac_util_access_terminal_sw_version_validate(bcmolt_devid device);
+bcmos_errno mac_util_access_terminal_set(acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type);
+bcmos_errno mac_util_access_terminal_info_validate(const bcmbal_access_terminal_cfg *p_acc_term_req);
+
+bcmos_errno mac_util_subscriber_terminal_set(sub_term_inst *p_sub_term, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery);
+bcmos_errno mac_util_subscriber_terminal_info_validate(const bcmbal_subscriber_terminal_cfg *p_sub_term_req);
+
+bcmos_errno mac_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if op_type);
+
+bcmos_errno mac_util_flow_set(flow_inst *p_flow_core, bal_util_oper_flow op_type);
+bcmos_errno mac_util_flow_info_validate(const bcmbal_flow_cfg *p_flow_req);
+
+bcmos_errno mac_util_group_set(group_inst *p_flow, bal_util_oper_group op_type, bcmos_bool send_ind);
+bcmos_errno mac_util_group_info_validate(const bcmbal_group_cfg *p_group_req);
+
+bcmos_errno mac_util_tm_sched_info_validate(const bcmbal_tm_sched_cfg *p_tm_sched_req);
+bcmos_errno mac_util_agg_port_set(tm_sched_inst *p_tm_sched, bal_util_oper_agg_port op_type);
+
+
+bcmos_errno mac_util_init(const char *maple_address);
+
+bcmos_errno mac_util_cli_init(bcmcli_entry *p_cli_dir);
+
+void mac_util_indication_cb(bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+bcmos_errno mac_util_finish(void);
+
+/* reporting functions to core */
+void mac_util_report_flow_add_success(bcmbal_flow_key flow_key, uint32_t pon_if);
+void mac_util_report_flow_add_failed(bcmbal_flow_key flow_key, uint32_t pon_if, bcmos_errno err);
+void mac_util_report_flow_remove_success(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type);
+void mac_util_report_flow_remove_failed(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type, bcmos_errno err);
+
+void mac_util_report_tm_sched_set_indication (bcmbal_tm_sched_key tm_sched_key, bcmos_errno err, bcmolt_result ind_result);
+
+/** @brief handler routine type for maple indication handlers */
+typedef bcmos_errno (mac_util_olt_ind_handler)(bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+/** @brief generic struct for maple indication object types and handlers that would be be handled in mac util */
+typedef struct mac_util_olt_ind_obj_and_handlers
+{
+ bcmolt_obj_id obj_type;
+ char obj_type_str[50];
+ mac_util_olt_ind_handler *ind_handler;
+} mac_util_ind_obj_and_handlers;
+
+
+char *_mac_util_get_obj_type_str_for_indications ( bcmolt_obj_id obj_type,
+ mac_util_ind_obj_and_handlers obj_types_and_handlers[], uint16_t num_obj_types);
+
+/* maple indication handlers */
+bcmos_errno mac_util_handle_all_olt_ind_for_gpon (bcmolt_devid device_id, bcmolt_msg *p_msg);
+bcmos_errno mac_util_handle_all_olt_ind_for_xgpon (bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+
+/* flow mgmt wrapper functions */
+flow_list_entry *_mac_util_db_flow_alloc (void);
+bcmos_errno _mac_util_db_flow_free (uint32_t pon_if, flow_list_entry *p_entry);
+
+bcmos_errno _mac_util_db_flow_add (uint32_t pon_if, flow_list_entry *p_entry);
+bcmos_errno _mac_util_db_flow_remove (uint32_t pon_if, flow_list_entry *p_entry);
+
+flow_list_entry *_mac_util_db_flow_get_w_flow_key (uint32_t pon_if, bcmbal_flow_key *p_flow_key);
+flow_list_entry *_mac_util_db_flow_get_next_w_flow_key (uint32_t pon_if, flow_list_entry *p_curr_entry, flow_list_entry **pp_next_entry);
+
+
+flow_list_entry *_mac_util_db_flow_get_next_w_sub_term_id (uint32_t pon_if, uint32_t sub_term_id,
+ flow_list_entry *p_curr_entry, flow_list_entry **pp_next_entry);
+
+
+bcmos_errno _mac_util_db_flow_count_w_gem (uint32_t pon_if, uint16_t gem_port_id, uint32_t *p_count);
+flow_list_entry *_mac_util_db_flow_get_next_w_gem (uint32_t pon_if, uint16_t gem_port_id,
+ void **pp_rsc_mgr_curr_entry, void **pp_rsc_mgr_next_entry);
+
+bcmos_errno _mac_util_db_flow_count_w_alloc_id (uint32_t pon_if, uint16_t alloc_id, uint32_t *p_count);
+flow_list_entry *_mac_util_db_flow_get_next_w_alloc_id (uint32_t pon_if, uint16_t alloc_id,
+ void **pp_rsc_mgr_curr_entry, void **pp_rsc_mgr_next_entry);
+
+/* interface set */
+bcmos_errno mac_util_interface_set_for_gpon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type);
+bcmos_errno mac_util_interface_set_for_xgpon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type);
+bcmos_errno mac_util_interface_set_for_loopback(acc_term_interface *p_interface_inst, bal_util_oper_if op_type);
+
+/* sub term validate */
+bcmos_errno mac_util_validate_subscriber_terminal_info_for_gpon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req);
+bcmos_errno mac_util_validate_subscriber_terminal_info_for_xgpon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req);
+
+/* sub term set */
+bcmos_errno mac_util_subscriber_terminal_set_for_gpon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery);
+bcmos_errno mac_util_subscriber_terminal_set_for_xgpon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery);
+bcmos_errno mac_util_subscriber_terminal_set_for_loopback(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery);
+
+/* flow validates */
+bcmos_errno mac_util_validate_flow_info_for_gpon(const bcmbal_flow_cfg *p_flow_req);
+bcmos_errno mac_util_validate_flow_info_for_xgpon(const bcmbal_flow_cfg *p_flow_req);
+
+
+/* flow sets */
+bcmos_errno mac_util_flow_set_for_gpon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core);
+bcmos_errno mac_util_flow_set_for_xgpon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core);
+bcmos_errno mac_util_flow_set_for_loopback(bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core);
+
+/* group sets */
+bcmos_errno mac_util_group_set_for_gpon (bcmbal_group_cfg *p_group_req, bal_util_oper_group op_type, group_inst *p_group_context);
+bcmos_errno mac_util_group_set_for_xgpon (bcmbal_group_cfg *p_group_req, bal_util_oper_group op_type, group_inst *p_group_context);
+
+bcmos_errno maple_access_terminal_set_common (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+bcmos_errno maple_access_terminal_connect_common (bcmolt_devid device_id);
+bcmos_errno mac_util_init_parse_mac_ip_and_port (const char *maple_address);
+
+
+/* Report events to core */
+void mac_util_report_acc_term_event(uint16_t event);
+void mac_util_report_if_event(bcmbal_intf_id intf_id,
+ bcmbal_intf_type intf_type,
+ bcmos_errno err,
+ bcmolt_result result,
+ bcmolt_pon_state new_state);
+bcmos_errno check_send_flow_bal_ind_msg(flow_list_entry *p_flow,
+ bcmos_errno err,
+ bcmolt_result ind_result);
+
+void mac_util_report_sub_term_event(bcmbal_intf_id pon_ni,
+ bcmbal_sub_id onu_id,
+ bcmolt_serial_number *p_serial_number,
+ bal_util_oper_sub_term oper,
+ bcmos_errno err,
+ bcmolt_result result,
+ bcmolt_activation_fail_reason fail_reason,
+ bcmolt_epon_tunnel_id tunnel_id);
+
+
+
+void mac_util_report_flow_auto_ind (uint32_t pon_if,
+ bcmbal_flow_key flow_key ,bal_util_oper_flow op_type, bal_util_flow_ind ind);
+
+
+#define MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM BCMOLT_GPON_ONU_ID_ANY
+
+#define GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(_if_id, _device_id, _physical_if_id) \
+ do \
+ { \
+ rc = bcm_topo_pon_get_logical2physical(_if_id, &(_device_id), &(_physical_if_id)); \
+ if (BCM_ERR_OK != rc) \
+ { \
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(_if_id), \
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc)); \
+ return rc; \
+ } \
+ } \
+ while (0)
+
+
+/*@}*/
+#endif /* BAL_MAC_UTIL_H */
+
+
+
diff --git a/bal_release/src/core/util/mac/bal_mac_util_common_itu_pon.c b/bal_release/src/core/util/mac/bal_mac_util_common_itu_pon.c
new file mode 100644
index 0000000..e44a574
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_common_itu_pon.c
@@ -0,0 +1,1336 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_common_itu_pon.c
+ *
+ * @brief mac util interfaces definition used by Bal Core, for ITU PON flavors : GPON, XG-PON1, XGS-PON , NG-PON2
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+#include <bal_mac_util_common_itu_pon.h>
+#include <bcm_topo.h>
+
+
+
+/**
+ * @brief get string for the indication object type
+ */
+char *mac_util_indication_get_obj_type_str(bcmolt_obj_id obj_type, mac_util_ind_obj_and_handlers handlers[], size_t handlers_size)
+{
+ return _mac_util_get_obj_type_str_for_indications(obj_type, handlers, handlers_size);
+}
+
+
+/**
+ * @brief handle indications for any PON ITU flavor.
+ */
+bcmos_errno mac_util_handle_indication(bcmolt_devid device_id, bcmolt_msg *p_msg, mac_util_ind_obj_and_handlers handlers[], size_t handlers_size)
+{
+ int i = 0;
+ for(i=0; i < handlers_size; i++)
+ {
+ if(p_msg->obj_type == handlers[i].obj_type)
+ {
+ if(NULL != handlers[i].ind_handler)
+ {
+ return handlers[i].ind_handler(device_id, p_msg);
+ }
+ }
+ }
+ /* log an error if unhandled */
+ return BCM_ERR_INTERNAL;
+}
+
+
+
+/**
+ * @brief checks if a gem port is configured in OLT already for the same PON If and ONU
+ *
+ * @param svc_port_id gem port
+ * @param if_id PON NI
+ * @param onu_id ONU Id
+ * @param is_config_required TRUE/FALSE
+ * @param is_wait_for_indication TRUE/FALSE
+ *
+ * @return bcmos_errno
+ *
+ * @todo with multi-thread support in future, the code from checking the maple object
+ * to the actual config will need to be atomic(i.e. using mutex). This, to avoid closely parallel threads
+ * from getting a state of gem slightly before a new config another thread would make on the same gem,
+ * before this thread could configure it. This applies to both gem and alloc id checks.
+ *
+ */
+static bcmos_errno maple_mac_check_gem_port_id_config(uint16_t svc_port_id, uint32_t if_id, uint32_t onu_id,
+ bcmos_bool *is_config_required, bcmos_bool *is_wait_for_indication)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_sub_family pon_sub_family;
+ bcmos_bool is_configured = BCMOS_FALSE, is_activated = BCMOS_FALSE;
+
+ /* assume config is not required, if there is an error */
+ *is_config_required = BCMOS_FALSE;
+ *is_wait_for_indication = BCMOS_FALSE;
+
+ pon_sub_family = bcm_topo_pon_get_pon_sub_family(if_id);
+ switch(pon_sub_family)
+ {
+ case BCM_TOPO_PON_SUB_FAMILY_GPON:
+ {
+ rc = maple_gpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
+ }
+ break;
+
+ case BCM_TOPO_PON_SUB_FAMILY_XGPON:
+ {
+ rc = maple_xgpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
+ }
+ break;
+
+ default:
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ return rc;
+ }
+ *is_config_required = !is_configured;
+ *is_wait_for_indication = !is_activated;
+
+ if(BCMOS_FALSE == *is_config_required)
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s: gem port id is already configured: if_id = %d onu_id = %d svc_port_id = %d is_wait_for_indication = %s\n",
+ __FUNCTION__,
+ if_id, onu_id,svc_port_id,
+ (*is_wait_for_indication == BCMOS_TRUE ? "TRUE":"FALSE"));
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief Checks if a gem port needs to be actually deconfigured.
+ * This would be used during flow remove.
+ *
+ * @param svc_port_id gem port
+ * @param if_id PON NI
+ * @param onu_id ONU Id
+ * @param is_deconfig_required TRUE/FALSE
+ * @param is_wait_for_indication TRUE/FALSE
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_mac_check_gem_port_id_deconfig(uint16_t svc_port_id, uint32_t if_id, uint32_t onu_id,
+ bcmos_bool *is_deconfig_required, bcmos_bool *is_wait_for_indication)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t ref_count = 0;
+ bcm_topo_pon_mode pon_mode;
+ bcmos_bool is_configured = BCMOS_FALSE, is_activated = BCMOS_FALSE;
+
+ /* assume De-config not required, in case of an error */
+ *is_deconfig_required = BCMOS_FALSE;
+ *is_wait_for_indication = BCMOS_FALSE;
+
+ pon_mode = bcm_topo_pon_get_pon_mode(if_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ rc = maple_gpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
+ }
+ else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
+ {
+ rc = maple_xgpon_mac_check_gem_port_id(if_id, onu_id, svc_port_id, &is_configured, &is_activated);
+ }
+ else
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ return rc;
+ }
+
+ if(!is_configured)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s error in gpon gem port state: svc_port_id = %d if_id = %d onu_id = %d, gem state: NOT_CONFIGURED\n",
+ __FUNCTION__,
+ svc_port_id, if_id, onu_id);
+
+ return BCM_ERR_INTERNAL;
+ }
+
+
+ /** First: Check if gem deconfig is required:
+ * gem deconfig is not needed if other flows are still using the same gem, or it is already being deconfigured.
+ */
+#if RSRC_MGR_KEEPS_FLOW_LIST_PER_GEM
+ /** @todo the rsrc mgr ref count will not work for now since core fsm keeps the flow with admin down,
+ * though mac util does a clear on the gem.
+ */
+ /* get the ref count for the gem from rsc mgr */
+ rc = rsc_mgr_gem_lookup(if_id, svc_port_id, &ref_count);
+ if(BCM_ERR_OK != rc)
+ {
+ return BCM_ERR_PARM;
+ }
+#else
+ rc = _mac_util_db_flow_count_w_gem(if_id, svc_port_id, &ref_count);
+ if(BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+#endif
+
+ /* if more than 1 flow is using the gem in whatever state, skip deconfig */
+ if(1 < ref_count)
+ {
+ *is_deconfig_required = BCMOS_FALSE;
+ }
+ else
+ {
+ *is_deconfig_required = BCMOS_TRUE;
+ }
+
+ /* Gem port configuration indications are available on GPON only */
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ /** Next: Check if need to wait for indication */
+ if(BCMOS_TRUE == *is_deconfig_required)
+ {
+ if(!is_activated)
+ {
+ *is_wait_for_indication = BCMOS_FALSE;
+ }
+ else
+ {
+ *is_wait_for_indication = BCMOS_TRUE;
+ }
+ }
+ else
+ {
+ *is_wait_for_indication = BCMOS_FALSE;
+
+ }
+ }
+ else
+ {
+ *is_wait_for_indication = BCMOS_FALSE;
+ }
+
+
+ if(BCMOS_FALSE == *is_deconfig_required)
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "Skip gem port deconfig: is_deconfig_required = %s, is_wait_for_indication = %s, svc_port_id = %d if_id = %d onu_id = %d, [ref_count=%d, gem_is configured=%d, gem_is_activated=%d]\n",
+ (*is_deconfig_required == BCMOS_TRUE ? "TRUE":"FALSE"),
+ (*is_wait_for_indication == BCMOS_TRUE ? "TRUE":"FALSE"),
+ svc_port_id, if_id, onu_id,
+ ref_count, is_configured, is_activated);
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief maple_gem_port_id_add
+ *
+ * This routine is used for configuring at maple a specific gem port id on a given pon interface
+ * and assign it to a given onu id
+ * currently all sla properties are hard coded
+ *
+ * @param svc_port_id the gem port id
+ * @param if_id the interface id
+ * @param onu_id the onu id it will assign to
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_gem_port_id_add(uint16_t svc_port_id, uint32_t if_id, uint32_t onu_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gem_port_configuration configuration = {};
+ bcm_topo_pon_mode pon_mode;
+
+ if(onu_id < MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM)
+ {
+ configuration.direction = BCMOLT_GEM_PORT_DIRECTION_BIDIRECTIONAL;
+ configuration.type = BCMOLT_GEM_PORT_TYPE_UNICAST;
+ }
+ else
+ {
+ configuration.direction = BCMOLT_GEM_PORT_DIRECTION_DOWNSTREAM;
+ configuration.type = BCMOLT_GEM_PORT_TYPE_MULTICAST;
+ }
+
+ pon_mode = bcm_topo_pon_get_pon_mode(if_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ rc = maple_gpon_gem_port_id_add(if_id, svc_port_id, onu_id, &configuration);
+ }
+ else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
+ {
+ rc = maple_xgpon_gem_port_id_add(if_id, svc_port_id, onu_id, &configuration);
+ }
+ else
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief maple_gem_port_id_remove
+ *
+ * This routine is used Clear a specific gem port id config in OLT on a given pon interface.
+ *
+ * @param svc_port_id the gem port id
+ * @param if_id the interface id
+ *
+ * @return bcmos_errno
+ *
+ * @todo do we need to fill in all parameters to disable GEM or just the gem key ?
+ */
+static bcmos_errno maple_gem_port_id_remove(uint16_t svc_port_id, uint32_t if_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+
+ pon_mode = bcm_topo_pon_get_pon_mode(if_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ rc = maple_gpon_gem_port_id_remove(if_id, svc_port_id);
+ }
+ else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
+ {
+ rc = maple_xgpon_gem_port_id_remove(if_id, svc_port_id);
+ }
+ else
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "Failed to clear gem port configuration(%s) in OLT\n",
+ bcmos_strerror(rc));
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief checks if a alloc id is configured in OLT already for the same PON If and ONU
+ *
+ * @param agg_id alloc id
+ * @param if_id PON NI
+ * @param onu_id ONU Id
+ * @param p_alloc_id_state alloc id current state
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_mac_check_alloc_id_state(uint16_t agg_id, uint32_t if_id, uint32_t onu_id, bcmolt_alloc_state *p_alloc_id_state)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+
+ pon_mode = bcm_topo_pon_get_pon_mode(if_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ rc = maple_gpon_mac_get_alloc_id_config(if_id, onu_id, agg_id, p_alloc_id_state);
+ }
+ else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
+ {
+ rc = maple_xgpon_mac_get_alloc_id_config(if_id, onu_id, agg_id, p_alloc_id_state);
+ }
+ else
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ return rc;
+ }
+
+ return rc;
+}
+
+
+
+static bcmos_errno maple_mac_check_alloc_id_config(uint16_t agg_id, uint32_t if_id, uint32_t onu_id)
+{
+ bcmos_errno rc;
+ bcmolt_alloc_state alloc_id_state;
+
+
+ rc = maple_mac_check_alloc_id_state(agg_id, if_id, onu_id, &alloc_id_state);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",
+ __FUNCTION__, bcmos_strerror(rc));
+ return rc;
+ }
+ if(BCMOLT_ALLOC_STATE_NOT_CONFIGURED != alloc_id_state)
+ rc = BCM_ERR_PARM;
+ return rc;
+}
+static bcmos_errno maple_mac_check_alloc_id_active(uint16_t agg_id, uint32_t if_id, uint32_t onu_id, bcmos_bool *is_alloc_id_wait_for_ind)
+{
+ bcmos_errno rc;
+ bcmolt_alloc_state alloc_id_state;
+
+ rc = maple_mac_check_alloc_id_state(agg_id, if_id, onu_id, &alloc_id_state);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ return rc;
+ }
+ *is_alloc_id_wait_for_ind = BCMOLT_ALLOC_STATE_ACTIVE != alloc_id_state;
+ return rc;
+}
+
+/**
+ * @brief helper function to check flow with double tag and with action remove outer tag.
+ * Used for validation as well as flow config.
+ *
+ * @param p_flow_req A pointer to a flow object
+ *
+ * @return bcmos_errno
+ */
+bcmos_bool mac_util_check_flow_is_double_tag_remove_o_tag(const bcmbal_flow_cfg *p_flow_req)
+{
+ if(NULL != p_flow_req)
+ {
+ if(BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type &&
+ BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, action) &&
+ (p_flow_req->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG) &&
+ (p_flow_req->data.classifier.pkt_tag_type == BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG))
+ {
+ return BCMOS_TRUE;
+ }
+ }
+
+ return BCMOS_FALSE;
+}
+
+
+/**
+ * @brief maple_mac_unicast_flow_add
+ *
+ * This routine is used to configure a flow at the internal flows list to
+ * handle incoming and outgoing relevant indications.
+ * the flow svc_port is defined using a single gem port by a base_gem_port
+ * and single pbit(=0 in case of pbit is not available)
+ * it will also configure gem port and alloc id at the device if required.
+ *
+ *
+ * @param if_id - the pon interface id
+ * @param onu_id - the onu id
+ * @param agg_id - the alloc id
+ * @param sla - the sla configuration of the alloc id
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno maple_mac_agg_port_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla sla)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+ do
+ {
+ rc = maple_mac_check_alloc_id_config(agg_id, if_id, onu_id);
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "Failed to query alloc state\n");
+ break;
+ }
+
+ pon_mode = bcm_topo_pon_get_pon_mode(if_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ rc = maple_gpon_us_alloc_id_add(if_id, onu_id, agg_id, sla);
+ }
+ else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
+ {
+ rc = maple_xgpon_us_alloc_id_add(if_id, onu_id, agg_id, sla);
+ }
+ else
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ }
+ }while(0);
+ return rc;
+}
+
+/**
+ * @brief maple_mac_agg_port_remove
+ *
+ * This routine is used for De-configuring at maple a specific alloc_id on a given pon interface
+ *
+ * @param if_id - the pon interface id
+ *
+ * @param agg_id - the alloc id
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno maple_mac_agg_port_remove(uint32_t if_id, uint16_t agg_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_topo_pon_mode pon_mode;
+
+ pon_mode = bcm_topo_pon_get_pon_mode(if_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ rc = maple_gpon_us_alloc_id_remove(if_id, agg_id);
+ }
+ else if(BCM_TOPO_PON_SUB_FAMILY_XGPON == bcm_topo_pon_get_pon_sub_family(if_id))
+ {
+ rc = maple_xgpon_us_alloc_id_remove(if_id, agg_id);
+ }
+ else
+ {
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ }
+
+ return rc;
+}
+
+bcmos_errno maple_mac_unicast_flow_add(bcmbal_flow_cfg *p_flow, uint16_t pbit, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
+ flow_list_entry **pp_mac_util_flow_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmos_bool is_gem_config_required = BCMOS_TRUE;
+ bcmos_bool is_gem_wait_for_ind = BCMOS_TRUE , is_alloc_id_wait_for_ind = BCMOS_TRUE;
+ flow_list_entry *p_new_flow_entry = NULL;
+
+
+ *pp_mac_util_flow_entry = NULL;
+ do
+ {
+ /* Allocate & add the new flow to the flow list to follow indications/gem reuse/alloc reuse */
+ p_new_flow_entry = _mac_util_db_flow_alloc();
+ if(NULL == p_new_flow_entry)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to allocate the flow entry\n");
+ rc = BCM_ERR_NOMEM;
+ break;
+ }
+
+ memcpy(&p_new_flow_entry->bal_flow_key, &p_flow->key,
+ sizeof(bcmbal_flow_key));
+ p_new_flow_entry->if_id = p_flow->data.access_int_id;
+ p_new_flow_entry->sub_term_id = p_flow->data.sub_term_id;
+ p_new_flow_entry->svc_port_id = p_flow->data.svc_port_id;
+ if(BCMBAL_FLOW_TYPE_UPSTREAM == p_flow->key.flow_type)
+ {
+ p_new_flow_entry->agg_id = p_flow->data.agg_port_id;
+ }
+ p_new_flow_entry->vlan_id = per_flow_mode_vlan_id;
+ p_new_flow_entry->is_waiting_for_svc_port_active = BCMOS_TRUE;
+ p_new_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
+ p_new_flow_entry->is_configuration_completed = BCMOS_FALSE;
+
+
+ /* save the operation type so as to report back the right indication type to core on an indication from Maple */
+ p_new_flow_entry->op_type = op_type;
+
+ /* check if gem configuration is required or it was already configured,
+ could happen in case of us flow configured after a ds flow(with the same flow_id)
+ and vise versus, or if that is a case of different flow sharing the same gem port id */
+ if(BCMOS_TRUE == is_gem_config_required)
+ {
+ rc = maple_mac_check_gem_port_id_config(p_new_flow_entry->svc_port_id,
+ p_new_flow_entry->if_id,
+ p_new_flow_entry->sub_term_id,
+ &is_gem_config_required,
+ &is_gem_wait_for_ind);
+ if(BCM_ERR_OK != rc)
+ {
+ /* free the flow entry */
+ _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ /* set wait for ind flag */
+ p_new_flow_entry->is_waiting_for_svc_port_active = is_gem_wait_for_ind;
+ }
+
+ /* if that's an us flow, check if alloc configuration is required or it was already configured */
+ if(p_new_flow_entry->bal_flow_key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ {
+ rc = maple_mac_check_alloc_id_active(p_new_flow_entry->agg_id,
+ p_new_flow_entry->if_id,
+ p_new_flow_entry->sub_term_id,
+ &is_alloc_id_wait_for_ind);
+ if(BCM_ERR_OK != rc)
+ {
+ /* free the flow entry */
+ _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+
+ /* add the new flow to the flow DB */
+ rc = _mac_util_db_flow_add(p_flow->data.access_int_id, p_new_flow_entry);
+ if(BCM_ERR_OK != rc)
+ {
+ /* free the flow entry */
+ _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
+ break;
+ }
+
+ /* configure the gem port id if required */
+ if(BCMOS_TRUE == is_gem_config_required)
+ {
+ rc = maple_gem_port_id_add(p_new_flow_entry->svc_port_id, p_new_flow_entry->if_id, p_new_flow_entry->sub_term_id);
+ if(BCM_ERR_OK != rc)
+ {
+ break;
+ }
+ }
+
+ } while(0);
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, pbit=%d, if_id=%d, sub_term_id=%d, "
+ "svc_port_id=%d, agg_id=%d, vlan_id=%d, op type=%s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc,
+ p_flow->key.flow_id, p_flow->key.flow_type, pbit,
+ p_flow->data.access_int_id, p_flow->data.sub_term_id,
+ p_flow->data.svc_port_id, p_flow->data.agg_port_id, per_flow_mode_vlan_id,
+ (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW_ADD":"INVALID"));
+ }
+
+ /* set the arg to return the local flow entry to caller */
+ *pp_mac_util_flow_entry = p_new_flow_entry;
+
+ return rc;
+}
+
+
+/**
+ * @brief utility routine to correctly assign the SLAs to new tm sched owned by agg port
+ * This routine adjusts the BW values to be aligned with 8KBytes/sec boundary. It also
+ * adjusts the difference between pbr & sbr to be at least 32KBytes/sec
+ *
+ * @param p_tm_sched_req new tm sched instance
+ * @param p_agg_sla pointer to the sla configuration
+ *
+ * @note For Maple to accept the sla config:
+ * (1) the sbr and pbr values from BAL user should be in increments of 256 KBits/sec.
+ * (2) Also, the sbr should be at least 256 Kbits/sec less than the pbr.
+ * (3) sbr value can be 0 or else at least 256 Kbits/sec
+ * (4) pbr value can be 256 Kbits/sec or above
+ *
+ * @note The SLA is used for the upstream alloc_id really, even though this is being called for downstream and upstream.
+ *
+ */
+void mac_util_assign_agg_port_sla(bcmbal_tm_sched_cfg *p_tm_sched_req, bcmolt_pon_alloc_sla *p_agg_sla)
+{
+
+ BUG_ON(NULL == p_tm_sched_req);
+
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.rate,tm_shaping, sbr))
+ {
+ p_agg_sla->guaranteed_bw = KILOBITS_PER_SEC2BYTES_PER_SEC(p_tm_sched_req->data.rate.sbr);
+ /* Align the BW to 8KBytes granularity(always upward adjustment) */
+ p_agg_sla->guaranteed_bw = SLA_BW_NKBYTES_ALIGNED(p_agg_sla->guaranteed_bw, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.rate, tm_shaping, pbr))
+ {
+ p_agg_sla->maximum_bw = KILOBITS_PER_SEC2BYTES_PER_SEC(p_tm_sched_req->data.rate.pbr);
+ /* max rate should be bigger by 32KBytes/sec than guaranteed rate */
+ if(MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID >(p_agg_sla->maximum_bw - p_agg_sla->guaranteed_bw))
+ {
+ p_agg_sla->maximum_bw = p_agg_sla->guaranteed_bw + MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID;
+ }
+ else
+ {
+ /* Else, align the BW to 8KBytes granularity(always upward adjustment) */
+ p_agg_sla->maximum_bw = SLA_BW_NKBYTES_ALIGNED(p_agg_sla->maximum_bw, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
+ }
+ }
+ else
+ {
+ /* max rate should be bigger by 32KBytes/sec than guaranteed rate */
+ p_agg_sla->maximum_bw = p_agg_sla->guaranteed_bw + MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID;
+ }
+ }
+ else if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.rate, tm_shaping, pbr))
+ {
+ p_agg_sla->maximum_bw = KILOBITS_PER_SEC2BYTES_PER_SEC(p_tm_sched_req->data.rate.pbr);
+
+ /* Align the BW to 8KBytes granularity(always upward adjustment) */
+ p_agg_sla->maximum_bw = SLA_BW_NKBYTES_ALIGNED(p_agg_sla->maximum_bw , MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
+ /* since only max_rate was specified, it is best effort, so set the min rate = 0 */
+ p_agg_sla->guaranteed_bw = 0;
+ }
+ else
+ {
+
+ /* Nothing is set, so assign the defaults(that suits GPON) times the SLA US rate factor(GPON=1, XG-PON1=2, XGS-PON,NG-PON2=8) */
+ p_agg_sla->guaranteed_bw = SLA_GUARANTEED_BW_DEFAULT_BYTES_PER_SEC * MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor;
+ p_agg_sla->maximum_bw = SLA_MAX_BW_DEFAULT_BYTES_PER_SEC * MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor;
+ }
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, nrt_cbr))
+ {
+ /* Align the BW to 8KBytes granularity(always upward adjustment) */
+ p_agg_sla->cbr_nrt_bw = SLA_BW_NKBYTES_ALIGNED(p_tm_sched_req->data.tcont_sla.nrt_cbr, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
+ }
+ else
+ {
+ p_agg_sla->cbr_nrt_bw = 0;
+ }
+
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, rt_cbr))
+ {
+ /* Align the BW to 8KBytes granularity(always upward adjustment) */
+ p_agg_sla->cbr_rt_bw = SLA_BW_NKBYTES_ALIGNED(p_tm_sched_req->data.tcont_sla.rt_cbr, MAC_UTIL_PMDB(p_tm_sched_req->data.owner.u.agg_port.intf_id).sla_us_rate_factor);
+ }
+ else
+ {
+ p_agg_sla->cbr_rt_bw = 0;
+ }
+
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, extra_bw_elig))
+ {
+ p_agg_sla->additional_bw_eligibility = p_tm_sched_req->data.tcont_sla.extra_bw_elig;
+ }
+ else
+ {
+ p_agg_sla->additional_bw_eligibility = BCMOLT_ADDITIONAL_BW_ELIGIBILITY_BEST_EFFORT;
+ }
+
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, rt_profile))
+ {
+ p_agg_sla->cbr_rt_ap_index = p_tm_sched_req->data.tcont_sla.rt_profile;
+ }
+ else
+ {
+ p_agg_sla->cbr_rt_ap_index = 0;
+ }
+
+ if(BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_tm_sched_req->data.tcont_sla, tm_tcont_sla, nrt_profile))
+ {
+ p_agg_sla->cbr_nrt_ap_index = p_tm_sched_req->data.tcont_sla.nrt_profile;
+ }
+ else
+ {
+ p_agg_sla->cbr_nrt_ap_index = 0;
+ }
+
+ p_agg_sla->alloc_type = BCMOLT_ALLOC_TYPE_NSR;
+ p_agg_sla->cbr_rt_compensation = BCMOS_FALSE;
+ p_agg_sla->weight = 0;
+ p_agg_sla->priority = 0;
+
+}
+
+
+/**
+ * @brief mark_flow_config_complete
+ *
+ * This routine is used to mark all related flow entries, that the flow configuration requests to device was completed,
+ * meaning now it is ready to be checked for configuration completion indication from device, and to be indicated to core.
+ *
+ * @param p_flow_entry pointer to mac util flow instance
+ *
+ * @return void
+ */
+void mac_util_mark_flow_config_complete(flow_list_entry *p_flow_entry)
+{
+ if(NULL != p_flow_entry)
+ {
+ p_flow_entry->is_configuration_completed = BCMOS_TRUE;
+ }
+}
+
+
+/**
+ * @brief maple_mac_broadcast_flow_add
+ *
+ * This routine is used for setting required configuration for a new broadcast flow :
+ * gem port id, iwf ds flow and configure it as a miss fallback of its assigned interface.
+ * it will also create an entry for the new flow at the internal flows list to follow relevant indication
+ *
+ * @param p_flow A pointer to a flow object
+ * @param per_flow_mode_vlan_id vlan id used for GEM port mapping in per flow mode
+ * @param op_type flow "add" or "modify"
+ * @param pp_mac_util_flow_entry addr of pointer to flow entry in mac util DB
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno maple_mac_broadcast_flow_add(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
+ flow_list_entry **pp_mac_util_flow_entry)
+{
+ bcmos_errno rc = BCM_ERR_PARM;
+ flow_list_entry *p_new_flow_entry = NULL;
+ bcmolt_gpon_iwf_ds_ingress_flow_key in_key;
+ bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg;
+ bcmolt_gpon_iwf_ds_egress_flow_key egr_key;
+ bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg;
+ bcmolt_gpon_iwf_key iwf_key;
+ bcmolt_gpon_iwf_cfg get_iwf_cfg, set_iwf_cfg;
+ bcmolt_mac_table_configuration mac_table_configuration;
+ bcmos_bool is_gem_config_required = BCMOS_TRUE;
+ bcmos_bool is_gem_wait_for_ind = BCMOS_TRUE;
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+ bcm_topo_pon_mode pon_mode;
+
+ *pp_mac_util_flow_entry = NULL;
+
+ /* add the new flow to the flow list */
+ p_new_flow_entry = _mac_util_db_flow_alloc();
+ if(NULL == p_new_flow_entry)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to allocate the flow entry\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ memcpy(&p_new_flow_entry->bal_flow_key, &p_flow->key, sizeof(bcmbal_flow_key));
+ p_new_flow_entry->if_id = p_flow->data.access_int_id;
+ p_new_flow_entry->sub_term_id = p_flow->data.sub_term_id;
+ p_new_flow_entry->svc_port_id = p_flow->data.svc_port_id;
+ /* broadcast gem are active by default once they are set, no indications */
+ p_new_flow_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
+ p_new_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
+ p_new_flow_entry->is_configuration_completed = BCMOS_FALSE;
+
+ /* make sure the broadcast gem port is not already configured / assigned to any onu on the if */
+ rc = maple_mac_check_gem_port_id_config(p_new_flow_entry->svc_port_id,
+ p_new_flow_entry->if_id,
+ p_new_flow_entry->sub_term_id,
+ &is_gem_config_required,
+ &is_gem_wait_for_ind);
+ if(BCM_ERR_OK != rc)
+ {
+ /* free the flow */
+ _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
+ return BCM_ERR_PARM;
+ }
+
+ if(BCMOS_FALSE == is_gem_config_required)
+ {
+ /* some error, can't have the broadcast flow already configured for the onu */
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Gem %d is already configured on if %d(assigned to onu_id %d)\n",
+ p_new_flow_entry->svc_port_id, p_new_flow_entry->if_id, p_new_flow_entry->sub_term_id);
+
+ /* free the flow */
+ _mac_util_db_flow_free(p_flow->data.access_int_id, p_new_flow_entry);
+ return BCM_ERR_PARM;
+ }
+
+ /* add the new flow to the local flows list */
+ rc = _mac_util_db_flow_add(p_flow->data.access_int_id, p_new_flow_entry);
+ if(BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ /* a broadcast gem port is 'assigned' to the special MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM onu id */
+ rc = maple_gem_port_id_add(p_new_flow_entry->svc_port_id, p_new_flow_entry->if_id, MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM);
+ if(BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical(p_flow->data.access_int_id, &device_id, &physical_if_id);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to get physical if from logical if(%s)\n", bcmos_strerror(rc));
+ return rc;
+ }
+
+ /* Inter-working(IWF) stuff is relevant for GPON only */
+ pon_mode = bcm_topo_pon_get_pon_mode(p_flow->data.access_int_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ /* configure the ingress flow as default fallback ingress flow */
+ in_key.pon_ni = physical_if_id;
+ in_key.vlan_id = per_flow_mode_vlan_id;
+ BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_method,
+ BCMOLT_VLAN_TO_FLOW_MAPPING_METHOD_MACPLUSVID);
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_tag,
+ BCMOLT_MAPPING_TAG_METHOD_OUTER_VID);
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, vlan_action, BCMOLT_DS_VLAN_ACTION_TRANSPARENT);
+
+
+ rc = bcmolt_cfg_set(device_id, &in_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to configure ingress flow pon_ni = %d vlan_id = %d rc = %s(%d), err_text = %s\n",
+ in_key.pon_ni, in_key.vlan_id, bcmos_strerror(rc), rc, in_cfg.hdr.hdr.err_text);
+ return rc;
+ }
+
+ /* configure the egress flow as default fallback egress flow */
+ egr_key.pon_ni = physical_if_id;
+ egr_key.flow_id = p_flow->data.svc_port_id;
+
+ /* Configure DS egress handling: flow -> GEM */
+ BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
+ BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, gem_port, p_flow->data.svc_port_id);
+ BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, pbit_control, BCMOS_FALSE);
+
+ rc = bcmolt_cfg_set(device_id, &egr_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to configure egress flow pon_ni = %d, rc = %s(%d), err_text = %s\n",
+ egr_key.pon_ni, bcmos_strerror(rc), rc, egr_cfg.hdr.hdr.err_text);
+ return rc;
+ }
+
+ /* update the if miss fallback flow */
+ iwf_key.pon_ni = physical_if_id;
+ BCMOLT_CFG_INIT(&get_iwf_cfg, gpon_iwf, iwf_key);
+ BCMOLT_CFG_INIT(&set_iwf_cfg, gpon_iwf, iwf_key);
+
+ BCMOLT_CFG_PROP_GET(&get_iwf_cfg, gpon_iwf, all_properties);
+ rc = bcmolt_cfg_get(device_id, &get_iwf_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ mac_table_configuration = get_iwf_cfg.data.mac_table_configuration;
+ mac_table_configuration.miss_fallback = BCMOLT_MAC_TABLE_MISS_FALLBACK_DEFAULT_FLOW;
+ mac_table_configuration.default_flow_id = egr_key.flow_id;
+ BCMOLT_CFG_PROP_SET(&set_iwf_cfg, gpon_iwf, mac_table_configuration, mac_table_configuration);
+
+ rc = bcmolt_cfg_set(device_id, &set_iwf_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to configure iwf: pon_ni = %d, rc = %s(%d), err_text = %s\n",
+ iwf_key.pon_ni, bcmos_strerror(rc), rc, set_iwf_cfg.hdr.hdr.err_text);
+ return rc;
+ }
+ }
+
+ p_new_flow_entry->is_configuration_completed = BCMOS_TRUE;
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, if_id=%d, sub_term_id=%d, "
+ "svc_port_id=%d, agg_id=%d, vlan_id=%d, op type=%s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc,
+ p_flow->key.flow_id, p_flow->key.flow_type,
+ p_flow->data.access_int_id, p_flow->data.sub_term_id,
+ p_flow->data.svc_port_id, p_flow->data.agg_port_id, per_flow_mode_vlan_id,
+ (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW_ADD": "INVALID"));
+ }
+
+ /* set the arg to return the local flow entry to caller */
+ *pp_mac_util_flow_entry = p_new_flow_entry;
+
+ return rc;
+}
+
+
+/**
+ * @brief maple_mac_broadcast_flow_remove
+ *
+ * This routine is removes a broadcast flow from Maple
+ *
+ * @param p_flow A pointer to a flow object
+ * @param per_flow_mode_vlan_id vlan id for per flow mode
+ * @param op_type flow "remove" or "clear"
+ * @param p_mac_util_flow_entry mac util flow entry
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno maple_mac_broadcast_flow_remove(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
+ flow_list_entry *p_mac_util_flow_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ flow_list_entry *p_target_flow_entry = NULL;
+ bcmolt_gpon_iwf_ds_ingress_flow_key in_key;
+ bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg;
+ bcmolt_gpon_iwf_ds_egress_flow_key egr_key;
+ bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg;
+ bcmolt_gpon_iwf_key iwf_key;
+ bcmolt_gpon_iwf_cfg set_iwf_cfg;
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+ bcm_topo_pon_mode pon_mode;
+
+ /* First find the flow in local database */
+ p_target_flow_entry = _mac_util_db_flow_get_w_flow_key(p_flow->data.access_int_id, &(p_flow->key));
+
+ if(NULL == p_target_flow_entry)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s: Failed to find the flow entry: flow id: %d, flow_type: %s\n",
+ __FUNCTION__,
+ p_flow->key.flow_id,
+ (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_BROADCAST ? "broadcast":"unicast/multicast"));
+
+ return BCM_ERR_NOENT;
+ }
+
+
+ /* broadcast gem are active by default once they are set, no indications */
+ p_target_flow_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
+ p_target_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
+ p_target_flow_entry->is_configuration_completed = BCMOS_FALSE;
+
+
+
+ /* clear broadcast gem port */
+ rc = maple_gem_port_id_remove(p_target_flow_entry->svc_port_id, p_target_flow_entry->if_id);
+ if(BCM_ERR_OK != rc)
+ {
+ return rc;
+ }
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical(p_flow->data.access_int_id, &device_id, &physical_if_id);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to get physical if from logical if(%s)\n", bcmos_strerror(rc));
+ return rc;
+ }
+
+ /* Inter-working(IWF) stuff is relevant for GPON only */
+ pon_mode = bcm_topo_pon_get_pon_mode(p_flow->data.access_int_id);
+ if(pon_mode == BCM_TOPO_PON_MODE_GPON)
+ {
+ /* clear the ingress flow as default fallback ingress flow */
+ in_key.pon_ni = physical_if_id;
+ in_key.vlan_id = per_flow_mode_vlan_id;
+ BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
+
+ rc = bcmolt_cfg_clear(device_id, &in_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to clear ingress flow pon_ni = %d vlan_id = %d rc = %s(%d)\n",
+ in_key.pon_ni, in_key.vlan_id, bcmos_strerror(rc), rc);
+
+ return rc;
+ }
+
+ /* clear the egress flow as default fallback egress flow */
+ egr_key.pon_ni = physical_if_id;
+ egr_key.flow_id = p_flow->data.svc_port_id;
+ /* Configure DS egress handling: flow -> GEM */
+ BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
+
+ rc = bcmolt_cfg_clear(device_id, &egr_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to clear egress flow pon_ni = %d gem port = %d rc = %s(%d)\n",
+ egr_key.pon_ni, egr_key.flow_id, bcmos_strerror(rc), rc);
+
+ return rc;
+ }
+
+ /* update the if miss fallback flow */
+ iwf_key.pon_ni = physical_if_id;
+ BCMOLT_CFG_INIT(&set_iwf_cfg, gpon_iwf, iwf_key);
+
+ rc = bcmolt_cfg_clear(device_id, &set_iwf_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to clear iwf flow pon_ni = %d rc = %s(%d)\n",
+ iwf_key.pon_ni, bcmos_strerror(rc), rc);
+
+ return rc;
+ }
+ }
+
+ /* all De-config done */
+ p_target_flow_entry->is_configuration_completed = BCMOS_TRUE;
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, if_id=%d, sub_term_id=%d, "
+ "svc_port_id=%d, agg_id=%d, vlan_id=%d, op type=%s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc,
+ p_flow->key.flow_id, p_flow->key.flow_type,
+ p_flow->data.access_int_id, p_flow->data.sub_term_id,
+ p_flow->data.svc_port_id, p_flow->data.agg_port_id, per_flow_mode_vlan_id,
+ (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW_REMOVE":(BAL_UTIL_OPER_FLOW_CLEAR == op_type ? "FLOW_CLEAR":"INVALID")));
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief maple_mac_unicast_flow_remove
+ *
+ * This routine is used to De-configure a flow at the internal flows list to
+ * handle incoming and outgoing relevant indications.
+ * It will also De-configure gem port and alloc id at the device if required.
+ *
+ * @param p_flow Pointer to the flow info
+ * @param op_type Flow operation type i.e. FLOW_REMOVE, FLOW_CLEAR
+ * @param p_mac_util_flow_entry Pointer to mac util flow entry
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno maple_mac_unicast_flow_remove(bcmbal_flow_cfg *p_flow, bal_util_oper_flow op_type,
+ flow_list_entry *p_mac_util_flow_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmos_bool is_gem_deconfig_required = BCMOS_TRUE;
+ bcmos_bool is_gem_wait_for_ind = BCMOS_TRUE;
+ flow_list_entry *p_target_flow_entry = NULL;
+
+ BUG_ON(NULL == p_mac_util_flow_entry);
+
+ do
+ {
+ p_target_flow_entry = p_mac_util_flow_entry;
+ p_target_flow_entry->is_waiting_for_svc_port_active = BCMOS_TRUE;
+ p_target_flow_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_NONE;
+ p_target_flow_entry->is_configuration_completed = BCMOS_FALSE;
+ /* save the operation type so as to report back the right indication type to core on an indication from Maple */
+ p_target_flow_entry->op_type = op_type;
+
+ /* check if gem configuration is used by other flows still.
+ could happen in case of us flow configured after a ds flow(with the same flow_id)
+ and vice versa, or if that is a case of different flow sharing the same gem port id */
+ if(BCMOS_TRUE == is_gem_deconfig_required)
+ {
+ rc = maple_mac_check_gem_port_id_deconfig(p_target_flow_entry->svc_port_id,
+ p_target_flow_entry->if_id,
+ p_target_flow_entry->sub_term_id,
+ &is_gem_deconfig_required,
+ &is_gem_wait_for_ind);
+ /* set wait for ind flag */
+ p_target_flow_entry->is_waiting_for_svc_port_active = is_gem_wait_for_ind;
+
+ if(BCM_ERR_OK != rc)
+ {
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+
+ /* do not remove the flow entry from local flows list yet; wait for indication before removing */
+ /* De-configure the gem port id if required */
+ if(BCMOS_TRUE == is_gem_deconfig_required)
+ {
+ rc = maple_gem_port_id_remove(p_target_flow_entry->svc_port_id, p_target_flow_entry->if_id);
+ if(BCM_ERR_OK != rc)
+ {
+ break;
+ }
+ }
+ } while(0);
+
+ if(BCM_ERR_OK != rc)
+ {
+ if(!((BCM_ERR_NOENT == rc) &&(BAL_UTIL_OPER_FLOW_CLEAR == op_type)))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s Failed: rc = %s(%d), flow Id/Type=%d/%d, if_id=%d, sub_term_id=%d, "
+ "svc_port_id=%d, agg_id=%d, op type=%s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc,
+ p_flow->key.flow_id, p_flow->key.flow_type,
+ p_flow->data.access_int_id, p_flow->data.sub_term_id,
+ p_flow->data.svc_port_id, p_flow->data.agg_port_id,
+ (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW_REMOVE":(BAL_UTIL_OPER_FLOW_CLEAR == op_type ? "FLOW_CLEAR":"INVALID")));
+ }
+ }
+
+ return rc;
+
+}
+bcmos_errno mac_util_update_flows_w_sub_term_update(uint32_t pon_if, uint32_t sub_term_id, maple_mac_check_gem_port_id check_gem_port_id_func, maple_mac_check_agg_port_id check_agg_port_id_func)
+{
+ flow_list_entry *p_current_entry = NULL;
+ flow_list_entry *p_next_entry = NULL;
+ bcmos_bool dummy;
+ bcmos_bool is_gem_activated;
+ bcmos_bool is_wait_for_gem_activated;
+ bcmolt_alloc_state alloc_id_state;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ /*find all related flows, check their state and update if needed*/
+ do
+ {
+ p_current_entry = _mac_util_db_flow_get_next_w_sub_term_id(pon_if, sub_term_id, p_current_entry, &p_next_entry);
+ if(NULL == p_current_entry)
+ break;
+
+ rc = check_gem_port_id_func(pon_if,sub_term_id, p_current_entry->svc_port_id, &dummy, &is_gem_activated);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ continue;
+ }
+
+ is_wait_for_gem_activated = !is_gem_activated;
+
+ if(p_current_entry->agg_id)
+ {
+ rc = check_agg_port_id_func(pon_if, sub_term_id, p_current_entry->agg_id, &alloc_id_state);
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ continue;
+ }
+ }
+
+ /*if something was changed.....*/
+ if(p_current_entry->is_waiting_for_svc_port_active != is_wait_for_gem_activated)
+ {
+ /*update current flow entry*/
+ p_current_entry->is_waiting_for_svc_port_active = is_wait_for_gem_activated;
+
+ /*check if a flow became up*/
+ if(p_current_entry->op_type == BAL_UTIL_OPER_FLOW_ADD
+ &&(is_wait_for_gem_activated)
+ && BAL_UTIL_FLOW_IND_SEND_FAIL != p_current_entry->ind_sent)
+ {
+ mac_util_report_flow_auto_ind(pon_if,p_current_entry->bal_flow_key,p_current_entry->op_type, BAL_UTIL_FLOW_IND_SEND_FAIL);
+ p_current_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_FAIL;
+ }
+ /*check if a flow became down*/
+ if(p_current_entry->op_type == BAL_UTIL_OPER_FLOW_ADD
+ &&(!is_wait_for_gem_activated)
+ &&(BAL_UTIL_FLOW_IND_SEND_SUCCESS != p_current_entry->ind_sent))
+ {
+ mac_util_report_flow_auto_ind(pon_if,p_current_entry->bal_flow_key,p_current_entry->op_type, BAL_UTIL_FLOW_IND_SEND_SUCCESS);
+ p_current_entry->ind_sent = BAL_UTIL_FLOW_IND_SEND_SUCCESS;
+ }
+ }
+ /* go through all flows(assigned with the given sub term) until break by
+ _mac_util_db_flow_get_next_w_sub_term_id returning NULL*/
+ }while(1);
+
+ return rc;
+}
+
+/**
+ * @brief agg_port set
+ * @param p_tm_sched_req pointer to tm_sched request structure from core
+ * @param op_type ADD, REMOVE or CLEAR
+ * @param p_tm_sched_inst pointer to the core tm sched Object instance
+ *
+ * @return errno error
+ *
+ */
+bcmos_errno maple_mac_util_agg_port_set(bcmbal_tm_sched_cfg *p_tm_sched_req, bal_util_oper_agg_port op_type, tm_sched_inst *p_tm_sched_inst)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ do
+ {
+ /* Check the operation id */
+ if((BAL_UTIL_OPER_AGG_PORT_ADD != op_type) &&
+ (BAL_UTIL_OPER_AGG_PORT_REMOVE != op_type) &&
+ (BAL_UTIL_OPER_AGG_PORT_REMOVE != op_type))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_tm_sched_req->data.owner.u.agg_port.intf_id),
+ "Unexpected mac_util agg port operation %d \n", op_type);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /* agg port Add or Modify */
+ if(BAL_UTIL_OPER_AGG_PORT_ADD == op_type)
+ {
+ bcmolt_pon_alloc_sla agg_sla;
+ mac_util_assign_agg_port_sla(p_tm_sched_req, &agg_sla);
+ ret = maple_mac_agg_port_add(p_tm_sched_req->data.owner.u.agg_port.intf_id, p_tm_sched_req->data.owner.u.agg_port.sub_term_id, p_tm_sched_req->data.owner.u.agg_port.agg_port_id, agg_sla);
+ }
+ if(BAL_UTIL_OPER_AGG_PORT_REMOVE== op_type)
+ {
+ ret = maple_mac_agg_port_remove(p_tm_sched_req->data.owner.u.agg_port.intf_id, p_tm_sched_req->data.owner.u.agg_port.agg_port_id);
+ }
+
+ }while(0);
+ return ret;
+
+}
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util_common_itu_pon.h b/bal_release/src/core/util/mac/bal_mac_util_common_itu_pon.h
new file mode 100644
index 0000000..8f0f75f
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_common_itu_pon.h
@@ -0,0 +1,200 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_common_itu_pon.h
+ *
+ * @brief mac util interfaces definition used by Bal Core, for ITU PON: GPON, XG-PON1, XGS-PON
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+
+/**
+ * @brief Maple SLA bandwidth config request is aligned to 8000 Bytes/sec
+ *
+ * @note similar macros are defined in bcm_common_gpon.h embedded code.
+ */
+#define MAPLE_BW_GRANULARITY_BYTES 8000
+#define MAPLE_BW_GRANULARITY_BYTES_10G 16000
+#define MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID 32000
+#define SLA_BW_NKBYTES_ALIGNED(_rate, _us_rate_factor) \
+ (_us_rate_factor) == 8 ? \
+ ((((_rate) + MAPLE_BW_GRANULARITY_BYTES_10G-1) / MAPLE_BW_GRANULARITY_BYTES_10G) * MAPLE_BW_GRANULARITY_BYTES_10G) : \
+ ((((_rate) + MAPLE_BW_GRANULARITY_BYTES-1) / MAPLE_BW_GRANULARITY_BYTES) * MAPLE_BW_GRANULARITY_BYTES)
+
+/* The thumb-rule is GPON PON capacity (155520000 Bps) divided by the maximum number of ONUs (128), rounded by granularity constraint. */
+#define SLA_GUARANTEED_BW_DEFAULT_BYTES_PER_SEC 1208000
+/* Like the default guaranteed BW, but since we are going to configure best-effort class, additional BW must be bigger than guaranteed BW in at least 32000. */
+#define SLA_MAX_BW_DEFAULT_BYTES_PER_SEC (SLA_GUARANTEED_BW_DEFAULT_BYTES_PER_SEC + MAPLE_MIN_BYTES_PER_SEC_FOR_DEFAULT_ALLOC_ID)
+#define KILOBITS_PER_SEC2BYTES_PER_SEC(x) ((uint64_t)(x) * 1000 / 8)
+
+
+char *mac_util_indication_get_obj_type_str (bcmolt_obj_id obj_type, mac_util_ind_obj_and_handlers handlers[], size_t handlers_size);
+bcmos_errno mac_util_handle_indication (bcmolt_devid device_id, bcmolt_msg *p_msg, mac_util_ind_obj_and_handlers handlers[], size_t handlers_size);
+bcmos_bool mac_util_check_flow_is_double_tag_remove_o_tag (const bcmbal_flow_cfg *p_flow_req);
+void mac_util_assign_agg_port_sla (bcmbal_tm_sched_cfg *p_tm_sched_req, bcmolt_pon_alloc_sla *p_agg_sla);
+
+bcmos_errno maple_mac_unicast_flow_add (bcmbal_flow_cfg *p_flow, uint16_t pbit, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type, flow_list_entry **pp_mac_util_flow_entry);
+bcmos_errno maple_mac_unicast_flow_remove (bcmbal_flow_cfg *p_flow, bal_util_oper_flow op_type, flow_list_entry *p_mac_util_flow_entry);
+bcmos_errno maple_mac_broadcast_flow_add (bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type,
+ flow_list_entry **pp_mac_util_flow_entry);
+bcmos_errno maple_mac_broadcast_flow_remove (bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bal_util_oper_flow op_type, flow_list_entry *p_mac_util_flow_entry);
+void mac_util_mark_flow_config_complete(flow_list_entry *p_flow_entry);
+bcmos_errno maple_gpon_mac_check_gem_port_id(uint32_t if_id, uint32_t onu_id, uint16_t svc_port_id,
+ bcmos_bool *is_configured, bcmos_bool *is_activated);
+bcmos_errno maple_xgpon_mac_check_gem_port_id(uint32_t if_id, uint32_t onu_id, uint16_t svc_port_id,
+ bcmos_bool *is_configured, bcmos_bool *is_activated);
+bcmos_errno maple_gpon_gem_port_id_add(uint32_t if_id, uint16_t svc_port_id, uint32_t onu_id, bcmolt_gem_port_configuration *configuration);
+bcmos_errno maple_xgpon_gem_port_id_add(uint32_t if_id, uint16_t svc_port_id, uint32_t onu_id, bcmolt_gem_port_configuration *configuration);
+bcmos_errno maple_gpon_gem_port_id_remove(uint32_t if_id, uint16_t svc_port_id);
+bcmos_errno maple_xgpon_gem_port_id_remove(uint32_t if_id, uint16_t svc_port_id);
+bcmos_errno maple_gpon_mac_get_alloc_id_config (uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_alloc_state *alloc_id_state);
+
+bcmos_errno maple_xgpon_mac_get_alloc_id_config (uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_alloc_state *alloc_id_state);
+
+
+bcmos_errno maple_gpon_us_alloc_id_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla agg_sla);
+bcmos_errno maple_xgpon_us_alloc_id_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla agg_sla);
+bcmos_errno maple_gpon_us_alloc_id_remove(uint32_t if_id, uint16_t agg_id);
+bcmos_errno maple_xgpon_us_alloc_id_remove(uint32_t if_id, uint16_t agg_id);
+
+bcmos_errno maple_mac_agg_port_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla sla);
+bcmos_errno maple_mac_agg_port_remove(uint32_t if_id, uint16_t agg_id);
+
+
+
+/* functions to register for specific auto indications from maple */
+bcmos_errno _mac_util_register_for_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg,
+ mac_util_ind_obj_and_handlers obj_types_and_handlers[], uint16_t num_obj_types, bcmolt_devid device_id);
+bcmos_errno mac_util_register_for_device_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id);
+bcmos_errno mac_util_register_for_gpon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id);
+bcmos_errno mac_util_register_for_xgpon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id);
+
+
+/** @brief generic struct for object set/validate handlers based on mac protocols */
+typedef bcmos_errno (*mac_util_bal_group_validate_handler) (const bcmbal_group_cfg *p_group_req);
+typedef bcmos_errno (*mac_util_bal_group_set_handler) (bcmbal_group_cfg *p_group_req, bal_util_oper_group op_type, group_inst *p_group_context);
+typedef bcmos_errno (*mac_util_bal_flow_validate_handler) (const bcmbal_flow_cfg *p_flow_req);
+typedef bcmos_errno (*mac_util_bal_flow_set_handler) (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core);
+typedef bcmos_errno (*mac_util_bal_sub_term_validate_handler) (const bcmbal_subscriber_terminal_cfg *p_sub_term_req);
+typedef bcmos_errno (*mac_util_bal_sub_term_set_handler) (sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery);
+typedef bcmos_errno (*mac_util_bal_if_validate_handler) (acc_term_inst *p_acc_term, bal_util_oper_if op_type);
+typedef bcmos_errno (*mac_util_bal_if_set_handler) (acc_term_interface *p_interface_inst, bal_util_oper_if op_type);
+typedef bcmos_errno (*mac_util_bal_acc_term_set_handler) (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+typedef bcmos_errno (*mac_util_bal_acc_term_post_indication_set_handler) (bcmolt_devid device_id);
+
+
+/**
+ * Structure for handler routines for different pon modes and loopback mode
+ */
+typedef struct
+{
+ mac_util_bal_if_validate_handler if_validate;
+ mac_util_bal_if_set_handler if_set;
+
+ mac_util_bal_sub_term_validate_handler sub_term_validate;
+ mac_util_bal_sub_term_set_handler sub_term_set;
+
+ mac_util_bal_flow_validate_handler flow_validate;
+ mac_util_bal_flow_set_handler flow_set;
+
+ mac_util_bal_group_validate_handler group_validate;
+ mac_util_bal_group_set_handler group_set;
+
+ uint32_t sla_us_rate_factor;
+} mac_util_handlers_per_pon_mode_t;
+
+
+typedef bcmos_errno (* maple_mac_check_gem_port_id)(uint32_t if_id, uint32_t onu_id, uint16_t svc_port_id,
+ bcmos_bool *is_configured, bcmos_bool *is_activated);
+
+typedef bcmos_errno (* maple_mac_check_agg_port_id)(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_alloc_state *alloc_id_state);
+
+
+
+/** access terminal set */
+bcmos_errno mac_util_access_terminal_set_for_gpon_16 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+bcmos_errno mac_util_access_terminal_set_for_gpon_8 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+bcmos_errno mac_util_access_terminal_set_for_xgpon_8 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+bcmos_errno mac_util_access_terminal_set_for_xgs (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+bcmos_errno mac_util_access_terminal_set_for_10G_itu_pon (bcmolt_device_cfg dev_cfg, bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_post_indication_set_for_gpon(bcmolt_devid device_id);
+bcmos_errno mac_util_access_terminal_post_indication_set_for_xgpon_xgs(bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_loopback (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id);
+
+bcmos_errno mac_util_update_flows_w_sub_term_update(uint32_t pon_if, uint32_t sub_term_id, maple_mac_check_gem_port_id check_gem_port_id_func, maple_mac_check_agg_port_id check_agg_port_id_func);
+bcmos_errno maple_mac_util_agg_port_set(bcmbal_tm_sched_cfg *p_tm_sched_req, bal_util_oper_agg_port op_type, tm_sched_inst *p_tm_sched_inst);
+
+
+
+/**
+ * Structure for handler routines for diffrent system modes and loopback mode
+ */
+typedef struct
+{
+ mac_util_bal_acc_term_set_handler acc_term_set;
+ mac_util_bal_acc_term_post_indication_set_handler acc_term_post_indication_set;
+} mac_util_bal_req_handlers_for_system_mode_t;
+#define MAC_UTIL_PMDB(pon) mac_util_bal_req_handlers_for_pon_mode[bcm_topo_pon_get_pon_mode((pon))]
+
+typedef struct
+{
+ bcmolt_iwf_mode iwf_mode;
+} mac_util_topo_pon_context;
+
+
+
+typedef struct
+{
+ bcmolt_system_mode system_mode;
+ bcmos_bool is_connected;
+} mac_util_device_context;
+
+typedef struct
+{
+ mac_util_device_context devices[BCM_TOPO_MAX_NUM_OF_DEVS];
+ bcmos_bool fail_reported; /*more that one device may fail to connect, we would like to send the fail event to core only once*/
+} mac_util_acc_term_connectivity;
+
+mac_util_acc_term_connectivity acc_term_connectivity;
+
+extern mac_util_handlers_per_pon_mode_t mac_util_bal_req_handlers_for_pon_mode[];
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util_db_apis.c b/bal_release/src/core/util/mac/bal_mac_util_db_apis.c
new file mode 100644
index 0000000..2a84cd0
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_db_apis.c
@@ -0,0 +1,545 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_db_apis.c
+ *
+ * @brief This file has the wrapper functions and the calls to database API functions.
+ * These wrapper functions are called by mac util code for DB operations.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+
+
+/**
+ * @brief flow DB macros
+ * */
+/** @brief max number of flow types stored in the DB.
+ * @details for now upstream & downstream unicast flows only are stored in the flow DB
+ * */
+#define MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES 2
+
+/** @brief check if flow type key is valid */
+#define MAC_UTIL_FLOW_DB_FLOW_TYPE_IS_VALID(_flow_type) \
+ ((_flow_type) >= BCMBAL_FLOW_TYPE_UPSTREAM && \
+ (_flow_type) <= MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES) \
+
+
+/**
+ * @brief maps {flow Id, flow_type} Key pair to an {Index, sub-Index} pair to access a flow entry in the Array DB.
+ * */
+#define MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX(_flow_id, _flow_type, _index, _sub_index) \
+ do \
+ { \
+ (_index) = (_sub_index) = 0; \
+ if(MAC_UTIL_FLOW_DB_FLOW_ID_IS_VALID(_flow_id)) \
+ { \
+ if(MAC_UTIL_FLOW_DB_FLOW_TYPE_IS_VALID(_flow_type)) \
+ { \
+ (_index) = (_flow_id) - mac_util_flow_id_start_val+1; \
+ (_sub_index) = (_flow_type) - 1; \
+ } \
+ } \
+ } while (0);
+
+
+/** @brief lookup an entry from the Array based on flow Id & type key pair */
+#define MAC_UTIL_FLOW_DB_ENTRY_GET(_flow_id, _flow_type, _flow_entry) \
+ do \
+ { \
+ (_flow_entry) = NULL; \
+ uint32_t _index, _sub_index; \
+ MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX((_flow_id), (_flow_type), (_index), (_sub_index)); \
+ if (!_index) \
+ break; \
+ _flow_entry = mac_util_db_flows_list[_index][_sub_index]; \
+ } while (0);
+
+
+/** @brief Get First non-NULL flow entry from the Array */
+#define MAC_UTIL_FLOW_DB_ENTRY_GET_FIRST(_p_first) \
+ do \
+ { \
+ int _i, _j; \
+ for (_i=1; _i<=BAL_ACC_TERM_MAX_FLOWS; _i++) \
+ { \
+ for (_j=0; _j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES; _j++) \
+ { \
+ (_p_first) = mac_util_db_flows_list[_i][_j]; \
+ if (_p_first) \
+ break; \
+ } \
+ if (_p_first) \
+ break; \
+ } \
+ } while (0)
+
+
+/** @brief Get Next non-NULL flow entry from the Array */
+#define MAC_UTIL_FLOW_DB_ENTRY_GET_NEXT(_p_curr, _pp_next) \
+ do \
+ { \
+ uint32_t _i, _j, _curr_i, _curr_j; \
+ *(_pp_next) = NULL; \
+ if (_p_curr) \
+ { \
+ MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX(_p_curr->bal_flow_key.flow_id, _p_curr->bal_flow_key.flow_type, _curr_i, _curr_j);\
+ for (_i = (_curr_j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES-1 ?_curr_i : _curr_i+1); \
+ _i<=BAL_ACC_TERM_MAX_FLOWS; \
+ _i++) \
+ { \
+ for (_j= (_curr_j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES-1 ? _curr_j+1 : 0); \
+ _j<MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES; \
+ _j++) \
+ { \
+ *(_pp_next) = mac_util_db_flows_list[_i][_j]; \
+ if (*(_pp_next)) \
+ break; \
+ } \
+ if (*(_pp_next)) \
+ break; \
+ } \
+ } \
+ else \
+ break; \
+ } while (0)
+
+
+/** @brief Set a flow entry in the Array */
+#define MAC_UTIL_FLOW_DB_ENTRY_SET(_flow_id, _flow_type, _flow_entry, _rc) \
+ do \
+ { \
+ uint32_t _index, _sub_index; \
+ MAC_UTIL_FLOW_DB_FLOW_ID_TYPE2ARR_INDEX_SUB_INDEX((_flow_id), (_flow_type), (_index), (_sub_index)); \
+ if (!_index) \
+ { \
+ (_rc) = BCM_ERR_NULL; \
+ break; \
+ } \
+ mac_util_db_flows_list[_index][_sub_index] = (_flow_entry); \
+ } while (0);
+
+
+/**
+ * @brief flow Id starting value that can used by SDN User application.
+ * @details By default the starting flow Id is assumed to be 1.
+ */
+uint32_t mac_util_flow_id_start_val = 1;
+
+/**
+ * @brief flow DB Array
+ * @details This Array is for upstream & downstream flows and can store BAL_ACC_TERM_MAX_FLOWS flows.
+ * This array is indexed by BAL flow Id.
+ *
+ * @note First entry starts at index 1; (0 is not used).
+ *
+ * @note Upstream & Downstream flow types of a pair may use the same Flow Id.Hence there is a sub-array
+ * of each of Flow Id entry. The sub array has upstream flow entry in index 0 and downstream at index 1.
+ * Hence, a flow entry is accessible by the key pair {flowId, flowtype}.
+ * */
+static flow_list_entry *mac_util_db_flows_list[BAL_ACC_TERM_MAX_FLOWS + 1][MAC_UTIL_FLOW_DB_MAX_FLOW_TYPES];
+
+
+/*****************************************************************************/
+/** Flow DB wrapper Functions */
+
+/** @todo in future with a new DB data structure, these wrapper functions would
+ * be migrated to call those DB apis.
+ */
+/*****************************************************************************/
+
+/**
+ * @brief Allocate a new flow
+ *
+ * @return flow_list_entry pointer to a new flow entry
+ */
+flow_list_entry *_mac_util_db_flow_alloc (void)
+{
+ flow_list_entry *p_flow = NULL;
+
+ p_flow = bcmos_calloc(sizeof(flow_list_entry));
+ /* bcmos_calloc already initializes the memory to 0 */
+
+ return p_flow;
+}
+
+/**
+ * @brief Free a flow (free the memory or return it to free pool)
+ *
+ * @param pon_if pon interface id
+ * @param p_entry pointer to a flow entry
+ *
+ * @returns bcmos_errno bcm errno
+ *
+ * @note it checks if the flow being freed is already removed from flow DB
+ */
+bcmos_errno _mac_util_db_flow_free (uint32_t pon_if, flow_list_entry *p_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ return BCM_ERR_PARM;
+ }
+
+ if (NULL == p_entry)
+ {
+ return BCM_ERR_PARM;
+ }
+
+ /* free the memory */
+ bcmos_free(p_entry);
+
+ return rc;
+}
+
+/**
+ * @brief Add an already allocated flow to flow DB
+ *
+ * @param pon_if pon interface id
+ * @param p_entry pointer to a new flow entry
+ *
+ * @returns bcmos_errno bcm errno
+ *
+ * @todo in proper DB, it should check if the entry is already in the list or not
+ */
+bcmos_errno _mac_util_db_flow_add (uint32_t pon_if, flow_list_entry *p_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ return BCM_ERR_PARM;
+
+ if (!p_entry)
+ return BCM_ERR_PARM;
+
+ MAC_UTIL_FLOW_DB_ENTRY_SET(p_entry->bal_flow_key.flow_id, p_entry->bal_flow_key.flow_type, p_entry, rc);
+
+ return rc;
+}
+
+/**
+ * @brief Remove a flow entry from flow DB
+ *
+ * @param pon_if pon interface id
+ * @param p_entry pointer to a flow entry
+ *
+ * @returns bcmos_errno bcm errno
+ *
+ * @todo this API will be ported to different DB when we have one
+ */
+bcmos_errno _mac_util_db_flow_remove (uint32_t pon_if, flow_list_entry *p_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ return BCM_ERR_PARM;
+
+ if (!p_entry)
+ return BCM_ERR_PARM;
+
+ MAC_UTIL_FLOW_DB_ENTRY_SET(p_entry->bal_flow_key.flow_id, p_entry->bal_flow_key.flow_type, NULL, rc);
+
+ return rc;
+}
+
+/**
+ * @brief Lookup a flow based on a flow id and pon if
+ *
+ * @param pon_if pon interface id
+ * @param p_flow_key pointer to flow key
+ *
+ * @returns flow_list_entry pointer a flow entry in list
+ */
+flow_list_entry *_mac_util_db_flow_get_w_flow_key (uint32_t pon_if, bcmbal_flow_key *p_flow_key)
+{
+ flow_list_entry *p_flow = NULL;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ return NULL;
+ }
+
+ MAC_UTIL_FLOW_DB_ENTRY_GET(p_flow_key->flow_id, p_flow_key->flow_type, p_flow);
+
+ return p_flow;
+}
+
+/**
+ * @brief get next flow based on flow id and pon_if
+ *
+ * @param pon_if pon interface id
+ * @param p_curr_entry pointer to current flow entry
+ * @param pp_next_entry double pointer to next flow entry
+ *
+ * @returns flow_list_entry pointer to next flow entry in DB
+ */
+flow_list_entry *_mac_util_db_flow_get_next_w_flow_key (uint32_t pon_if, flow_list_entry *p_curr_entry, flow_list_entry **pp_next_entry)
+{
+ flow_list_entry *p_tmp_entry = p_curr_entry;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
+ return NULL;
+ }
+
+ /** @note this while loop is to continue to iterate through the DB until an entry with matching pon If is found */
+ while (1)
+ {
+ if (NULL == p_tmp_entry)
+ {
+ /* get first flow */
+ MAC_UTIL_FLOW_DB_ENTRY_GET_FIRST(p_tmp_entry);
+ if (p_tmp_entry)
+ {
+ MAC_UTIL_FLOW_DB_ENTRY_GET_NEXT(p_tmp_entry, pp_next_entry);
+
+ if (p_tmp_entry && (pon_if == p_tmp_entry->if_id))
+ return p_tmp_entry;
+ }
+ else
+ break; /* at the end of list */
+ }
+ else
+ {
+ if (NULL != *pp_next_entry)
+ {
+ p_tmp_entry = *pp_next_entry;
+ MAC_UTIL_FLOW_DB_ENTRY_GET_NEXT(p_tmp_entry, pp_next_entry);
+
+ if (pon_if == p_tmp_entry->if_id)
+ return p_tmp_entry;
+ }
+ else
+ break; /* at the end of list */
+ }
+ }
+
+ return NULL;
+}
+
+
+/**
+ * @brief get next flow based on sub terminal id
+ *
+ * @param pon_if pon interface id
+ * @param sub_term_id sub term id as the key
+ * @param p_curr_entry pointer to current flow entry
+ * @param pp_next_entry double pointer to next flow entry
+ *
+ * @returns flow_list_entry pointer to next flow entry in DB
+ *
+ */
+flow_list_entry *_mac_util_db_flow_get_next_w_sub_term_id (uint32_t pon_if, uint32_t sub_term_id,
+ flow_list_entry *p_curr_entry, flow_list_entry **pp_next_entry)
+{
+ flow_list_entry *p_tmp_entry = NULL;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
+ return NULL;
+ }
+
+ p_tmp_entry = _mac_util_db_flow_get_next_w_flow_key (pon_if, p_curr_entry, pp_next_entry);
+
+ while (NULL != p_tmp_entry)
+ {
+ if (sub_term_id == p_tmp_entry->sub_term_id)
+ {
+ /* found sub_term match */
+ return p_tmp_entry;
+ }
+ /** @note passing tmp entry here because this is a getnext loop internal to this routine */
+ p_tmp_entry = _mac_util_db_flow_get_next_w_flow_key (pon_if, p_tmp_entry, pp_next_entry);
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief count of flows using a gem port and pon_if
+ *
+ * @param pon_if pon interface id
+ * @param gem_port_id gem port id as the key
+ * @param p_count pointer to U32 to save count of flows using the same gem port
+ *
+ * @returns bcmos_errno bcm errno
+ *
+ */
+bcmos_errno _mac_util_db_flow_count_w_gem (uint32_t pon_if, uint16_t gem_port_id, uint32_t *p_count)
+{
+ uint32_t count = 0;
+ flow_list_entry *p_tmp_entry = NULL;
+ void *p_rsc_mgr_curr_entry = NULL;
+ void *p_rsc_mgr_next_entry = NULL;
+
+ BUG_ON(NULL == p_count);
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
+ return BCM_ERR_PARM;
+ }
+
+ p_tmp_entry = _mac_util_db_flow_get_next_w_gem (pon_if, gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ while (NULL != p_tmp_entry)
+ {
+ count++;
+ p_tmp_entry = _mac_util_db_flow_get_next_w_gem (pon_if, gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ }
+
+ *p_count = count;
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief get next flow based on gem and pon if
+ *
+ * @param pon_if pon interface id
+ * @param gem_port_id gem port id as the key
+ * @param **pp_rsc_mgr_curr_entry double pointer to current entry in Rsrc Mgr Database
+ * @param **pp_rsc_mgr_next_entry double pointer to next entry in Rsrc Mgr Database
+ *
+ * @returns flow_list_entry pointer to next flow entry in DB
+ *
+ * @note this queries resource mgr DB
+ */
+flow_list_entry *_mac_util_db_flow_get_next_w_gem (uint32_t pon_if, uint16_t gem_port_id,
+ void **pp_rsc_mgr_curr_entry, void **pp_rsc_mgr_next_entry)
+{
+ flow_inst *p_core_flow_entry = NULL;
+ flow_list_entry *p_flow_entry = NULL;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
+ return NULL;
+ }
+
+ p_core_flow_entry = rsc_mgr_gem_get_next_user_data (pon_if, gem_port_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
+
+ while (NULL != p_core_flow_entry)
+ {
+ p_flow_entry = _mac_util_db_flow_get_w_flow_key(pon_if, &p_core_flow_entry->current_flow_info.key);
+ if (p_flow_entry)
+ {
+ /* found gem match */
+ return p_flow_entry;
+ }
+ p_core_flow_entry = rsc_mgr_gem_get_next_user_data (pon_if, gem_port_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
+ }
+
+ return NULL;
+}
+
+/**
+ * @brief count of flows using an alloc id and pon if
+ *
+ * @param pon_if pon interface id
+ * @param alloc_id alloc id as the key
+ * @param p_count pointer to U32 that save the count of flows using the same alloc id
+ *
+ * @returns bcmos_errno bcm errno
+ */
+bcmos_errno _mac_util_db_flow_count_w_alloc_id (uint32_t pon_if, uint16_t alloc_id, uint32_t *p_count)
+{
+ uint32_t count = 0;
+ flow_list_entry *p_tmp_entry = NULL;
+ void *p_rsc_mgr_curr_entry = NULL;
+ void *p_rsc_mgr_next_entry = NULL;
+
+ BUG_ON( NULL == p_count);
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
+ return BCM_ERR_PARM;
+ }
+
+ p_tmp_entry = _mac_util_db_flow_get_next_w_alloc_id (pon_if, alloc_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ while (NULL != p_tmp_entry)
+ {
+ count++;
+ p_tmp_entry = _mac_util_db_flow_get_next_w_alloc_id (pon_if, alloc_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ }
+
+ *p_count = count;
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief get next flow based on upstream alloc id and pon if
+ *
+ * @param pon_if pon interface id
+ * @param alloc_id alloc id as the key
+ * @param **pp_rsc_mgr_curr_entry double pointer to current entry in Rsrc Mgr Database
+ * @param **pp_rsc_mgr_next_entry double pointer to next entry in Rsrc Mgr Database
+ *
+ * @returns flow_list_entry pointer to next flow entry in DB
+ *
+ * @note this queries resource mgr DB
+ */
+flow_list_entry *_mac_util_db_flow_get_next_w_alloc_id (uint32_t pon_if, uint16_t alloc_id,
+ void **pp_rsc_mgr_curr_entry, void **pp_rsc_mgr_next_entry)
+{
+ flow_inst *p_core_flow_entry = NULL;
+ flow_list_entry *p_flow_entry = NULL;
+
+ if (!IS_VALID_PON_IF(pon_if))
+ {
+ BCM_LOG(ERROR,log_id_mac_util,"Invalid pon_if %d !", pon_if);
+ return NULL;
+ }
+
+ p_core_flow_entry = rsc_mgr_alloc_id_get_next_user_data(pon_if, alloc_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
+
+ while (NULL != p_core_flow_entry)
+ {
+ p_flow_entry = _mac_util_db_flow_get_w_flow_key(pon_if, &p_core_flow_entry->current_flow_info.key);
+ if (p_flow_entry)
+ {
+ /* found alloc id match */
+ return p_flow_entry;
+ }
+ p_core_flow_entry = rsc_mgr_alloc_id_get_next_user_data(pon_if, alloc_id, pp_rsc_mgr_curr_entry, pp_rsc_mgr_next_entry);
+ }
+
+ return NULL;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util_epon.c b/bal_release/src/core/util/mac/bal_mac_util_epon.c
new file mode 100644
index 0000000..cae8d26
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_epon.c
@@ -0,0 +1,1067 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_epon.c
+ *
+ * @brief mac util interfaces definition used by Bal Core for EPON
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+#include <bal_mac_util_epon.h>
+
+#if BAL_EPON_EXCLUDE
+#include <bcmolt_user_appl_epon_oam.h>
+#include <bal_oam_util.h>
+#include <bcmolt_eon.h>
+
+static bcmos_errno mac_util_indication_handle_for_epon_link (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_indication_handle_for_epon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+
+/** @brief array stores the list of EPON related auto indications from Maple to subscribe */
+static mac_util_ind_obj_and_handlers mac_util_epon_ind_handlers[] =
+{
+ {BCMOLT_OBJ_ID_EPON_LINK, "BCMOLT_OBJ_ID_EPON_LINK", mac_util_indication_handle_for_epon_link},
+ {BCMOLT_OBJ_ID_EPON_NI, "BCMOLT_OBJ_ID_EPON_NI", mac_util_indication_handle_for_epon_ni}
+};
+
+
+/* epon onu entry structure */
+typedef enum
+{
+ OAM_PROVISION_STATE_IDLE = 0, /**< idle - did not start yet */
+ OAM_PROVISION_STATE_STARTED, /**< started - waiting to configure traffic cb to send bal core flow up indication */
+ OAM_PROVISION_STATE_COMPLETED, /**< completed successfully */
+ OAM_PROVISION_STATE_FAIL/**< failed to complete oam provision */
+} oam_provision_state;
+
+#define MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC 16
+typedef struct epon_onu_list_entry epon_onu_list_entry;
+struct epon_onu_list_entry
+{
+ TAILQ_ENTRY(epon_onu_list_entry) next;
+ bcmbal_subscriber_terminal_key bal_onu_key; /* bal onu key */
+ bcmos_mac_address mac_address;
+ oam_provision_state oam_provision_state;
+ uint8_t waiting_flows_num;
+ bcmbal_flow_key flow_keys[MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC];
+ uint32_t tunnel_id;
+};
+
+
+static TAILQ_HEAD(epon_onu_list_head_t, epon_onu_list_entry) epon_onu_list;
+
+
+/** @todo needs to be ported to the topology stub function */
+static bcmolt_devid maple_device_from_interface_get(uint16_t access_int_id)
+{
+ /* For now, all interfaces map to device 0 */
+ return (bcmolt_devid)0;
+
+}
+
+
+static void epon_onu_list_add(epon_onu_list_entry *epon_onu_entry);
+static epon_onu_list_entry *epon_onu_list_find_by_mac(const bcmos_mac_address *mac_address);
+static epon_onu_list_entry *epon_onu_list_find_by_key(bcmbal_subscriber_terminal_key *key);
+static void epon_onu_list_remove_by_key(bcmbal_subscriber_terminal_key *key);
+
+static void mac_util_configure_traffic_cb(void *context,
+ bcmolt_devid device_id,
+ bcmolt_epon_ni epon_ni,
+ const bcmos_mac_address *mac_address,
+ bcmos_errno result);
+
+static void mac_util_unconfigure_traffic_cb(void *context,
+ bcmolt_devid device_id,
+ bcmolt_epon_ni epon_ni,
+ const bcmos_mac_address *mac_address,
+ bcmos_errno result);
+
+
+#define _mac_addr_fmt_str "<%02x:%02x:%02x:%02x:%02x:%02x>"
+#define _mac_addr_data(mac) \
+ (mac).u8[0], \
+ (mac).u8[1], \
+ (mac).u8[2], \
+ (mac).u8[3], \
+ (mac).u8[4], \
+ (mac).u8[5]
+
+
+static void mac_util_oam_negotiation_cb(void *context, bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac_address, bcmos_errno result)
+{
+
+ epon_onu_list_entry *p_onu_entry = context;
+ uint32_t logical_pon;
+ bcmos_errno rc;
+
+ do
+ {
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, epon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, epon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
+ "device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n",
+ device_id, epon_ni, _mac_addr_data(*mac_address), result == BCM_ERR_OK ? "success" : "fail");
+
+
+ mac_util_report_sub_term_event(logical_pon,
+ p_onu_entry->bal_onu_key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_ADD,
+ result,
+ result == BCM_ERR_OK ? BCMOLT_RESULT_SUCCESS : BCMOLT_RESULT_FAIL,
+ BCMOLT_ACTIVATION_FAIL_REASON_NONE,
+ result == BCM_ERR_OK ? p_onu_entry->tunnel_id : BCMBAL_INVALID_TUNNEL_ID);
+
+ }
+ while(0);
+
+}
+
+/**
+ * @brief get string for the indication object type for epon
+ */
+static char *mac_util_indication_get_obj_type_str_for_epon (bcmolt_obj_id obj_type)
+{
+ return _mac_util_get_obj_type_str_for_indications (obj_type, mac_util_epon_ind_handlers, BCM_SIZEOFARRAY(mac_util_epon_ind_handlers));
+}
+
+/**
+ * @brief all the maple indication handlers for epon
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ */
+bcmos_errno mac_util_handle_all_olt_ind_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ int i = 0;
+
+ BCM_LOG(DEBUG, log_id_mac_util,
+ "mac_util_indication_cb received indication obj=%d/%s group=%d subgroup=%d\n",
+ p_msg->obj_type, mac_util_indication_get_obj_type_str_for_epon(p_msg->obj_type),
+ p_msg->group, p_msg->subgroup);
+
+ for (i=0; i < BCM_SIZEOFARRAY(mac_util_epon_ind_handlers); i++)
+ {
+ if (p_msg->obj_type == mac_util_epon_ind_handlers[i].obj_type)
+ {
+ return mac_util_epon_ind_handlers[i].ind_handler (device_id, p_msg);
+ }
+ }
+
+ /* log an error if unhandled */
+ return BCM_ERR_INTERNAL;
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for EPON Link
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_epon_link (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+
+ do
+ {
+ if (BCMOLT_EPON_LINK_AUTO_ID_MPCP_DISCOVERED == p_msg->subgroup)
+ {
+ epon_onu_list_entry *p_onu_entry;
+ bcmolt_epon_link_mpcp_discovered * p_ind = (bcmolt_epon_link_mpcp_discovered*)p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.epon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.epon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "llid indication received obj=%d group=%d subgroup=%d err=%d; "
+ "link_status = %s (%d), llid = (0x%04x) tunnel_id = (0x%08x)\n",
+ p_msg->obj_type, p_msg->group, p_msg->subgroup, p_msg->err,
+ p_ind->data.link_info.link_status==BCMOLT_EPON_LINK_STATUS_DISCOVERED ? "Discovered" : "other",
+ p_ind->data.link_info.link_status,
+ p_ind->data.link_info.llid,
+ p_ind->data.link_info.tunnel_id);
+
+
+
+ if(NULL == (p_onu_entry = epon_onu_list_find_by_mac(&(p_ind->key.mac_address))))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Failed to find epon onu related to received frame captured\n");
+ rc = BCM_ERR_INTERNAL;
+ }
+ else
+ {
+
+ p_onu_entry->tunnel_id = p_ind->data.link_info.tunnel_id;
+ bal_oam_start_oam_negotiation(device_id,
+ p_ind->key.epon_ni,
+ &p_ind->key.mac_address,
+ mac_util_oam_negotiation_cb,
+ p_onu_entry);
+ }
+ }
+ }
+ while(0);
+
+ return rc;
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for EPON NI
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_epon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+ do
+ {
+
+ if (BCMOLT_EPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_epon_ni_state_change_completed * p_ind = (bcmolt_epon_ni_state_change_completed *)p_msg;
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.epon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.epon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), "Pon if %d is %s.\n", logical_pon,
+ BCMOLT_EPON_NI_EN_STATE_ENABLED == p_ind->data.new_state ? "up" : "down");
+
+ mac_util_report_if_event(logical_pon, BCMBAL_INTF_TYPE_PON, p_msg->err,
+ BCMOLT_RESULT_SUCCESS, p_ind->data.new_state);
+ }
+ else
+ {
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_epon_ni_key *p_pon_key = &(((bcmolt_epon_ni_state_change_completed*)p_msg)->key);
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->epon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->epon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj Epon_NI group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ }
+
+
+
+ }
+ while(0);
+ return rc;
+}
+
+
+/**
+ * @brief Maple auto indication register for specific EPON based indications
+ *
+ * @param p_rx_cfg handler config structure
+ * @param device_id specific device id (for multiple devices support)
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_register_for_epon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id)
+{
+ return _mac_util_register_for_auto_indications (p_rx_cfg, mac_util_epon_ind_handlers, BCM_SIZEOFARRAY(mac_util_epon_ind_handlers), device_id);
+}
+#endif /* BAL_EPON_EXCLUDE */
+
+static bcmos_errno mac_util_epon_access_terminal_set(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id,
+ bcmolt_system_mode system_mode,
+ bcmolt_nni_speed nni_speed)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_device_key key = {};
+ bcmolt_device_nni_speed nni_speed_cfg;
+ bcmolt_device_cfg dev_cfg;
+
+ rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ BCMOLT_CFG_INIT(&dev_cfg, device, key);
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, system_mode);
+
+ nni_speed_cfg.first_half = nni_speed;
+ nni_speed_cfg.second_half = nni_speed;
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, nni_speed, nni_speed_cfg);
+
+ /** @todo with multiple devices the mechanism to configure acces term will change */
+ rc = bcmolt_cfg_set(device_id, &dev_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ return maple_access_terminal_connect_common(device_id);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_8_tdma(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA,
+ BCMOLT_NNI_SPEED_GBPS_12P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_4_tdma(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA,
+ BCMOLT_NNI_SPEED_GBPS_12P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_16_1g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__16_X,
+ BCMOLT_NNI_SPEED_GBPS_2P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_8_1g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__8_X,
+ BCMOLT_NNI_SPEED_GBPS_2P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_4_1g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__4_X,
+ BCMOLT_NNI_SPEED_GBPS_2P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_8_10g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__8_X_10_G,
+ BCMOLT_NNI_SPEED_GBPS_12P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_4_10g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__4_X_10_G,
+ BCMOLT_NNI_SPEED_GBPS_12P5);
+}
+
+bcmos_errno mac_util_access_terminal_set_for_epon_2_10g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id)
+{
+ return mac_util_epon_access_terminal_set(
+ p_acc_term,
+ op_type,
+ device_id,
+ BCMOLT_SYSTEM_MODE_EPON__2_X_10_G,
+ BCMOLT_NNI_SPEED_GBPS_12P5);
+}
+
+/**
+ * @brief Command Set setup routine for interface up to mac application for EPON
+ *
+ * This routine is called by if_fsm in the BAL core to initialize the command
+ * set to up the interface of the mac application. The cmdset actually
+ * consists of two commands, one is to send the if up request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param op_type Operation type on access terminal/interface instance
+ *
+ * @return bcmos_errno
+ *
+ */
+bcmos_errno mac_util_interface_set_for_epon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key;
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical(intf_key.intf_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ return rc;
+ }
+
+ bcmolt_epon_ni_key key;
+ bcmolt_epon_ni_cfg cfg;
+ bcmolt_epon_ni_set_epon_ni_en_state oper;
+
+ key.epon_ni = physical_if_id;
+
+ BCMOLT_CFG_INIT(&cfg, epon_ni, key);
+
+ if (BAL_UTIL_OPER_IF_UP == op_type)
+ {
+ BCMOLT_CFG_PROP_SET(&cfg, epon_ni, registration_behavior, BCMOLT_REGISTRATION_BEHAVIOR_NOTIFY_UNKNOWN);
+
+ bcmolt_cfg_set(device_id, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to %s (set) pon interface (%d) - %s, err_text=%s\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
+ rc, bcmos_strerror(rc), cfg.hdr.hdr.err_text);
+ return rc;
+ }
+ }
+
+ BCMOLT_OPER_INIT(&oper, epon_ni, set_epon_ni_en_state, key);
+ BCMOLT_OPER_PROP_SET(&oper, epon_ni, set_epon_ni_en_state, new_state,
+ (BAL_UTIL_OPER_IF_UP == op_type ?
+ BCMOLT_EPON_NI_EN_STATE_ENABLED : BCMOLT_EPON_NI_EN_STATE_DISABLED));
+
+ rc = bcmolt_oper_submit(device_id, &oper.hdr);
+
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to %s (submit) pon interface (%d) - %s, err_text=%s\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
+ rc, bcmos_strerror(rc), oper.hdr.hdr.err_text);
+ }
+ else
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Submitted INTERFACE-%s operation for IF %d\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "UP" : "DOWN", intf_key.intf_id);
+ }
+
+ return rc;
+}
+/*---------------------------------------------------------------------------------------------*/
+
+
+
+
+
+#if BAL_EPON_EXCLUDE
+/**
+ * @brief mac_util_validate_subscriber_terminal_info_for_epon
+ *
+ * This routine is used to validate all input attributes required for a sub term setting
+ * received from core for EPON
+ *
+ * @param p_sub_term_req A pointer to a subscriber terminal object
+ *
+ * @return bcmos_errno
+ */
+/*****************************************************************************/
+bcmos_errno mac_util_validate_subscriber_terminal_info_for_epon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req)
+{
+ if(BCMBAL_STATE_UP == p_sub_term_req->data.admin_state)
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET(p_sub_term_req, subscriber_terminal, mac_address))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "mac_address is a mandatory parameter for an epon subscriber terminal, and it is not set\n");
+ return BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief Command Set setup routine for subscriber terminal connect to mac application for EPON
+ *
+ * This routine is called by sub_term_fsm in the BAL core to initialize the command
+ * set to connect the subscriber terminal of the mac application. The cmdset actually
+ * consists of two commands, one is to send the sub_term request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_sub_term_inst A pointer to a subscriber terminal instance
+ * @param op_type Type of operation being performed on the subscriber terminal instance
+ * @param is_post_discovery This parameter is ignored for epon
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_subscriber_terminal_set_for_epon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
+
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "IN : %s pon_id = %d onu_id= %d "
+ "omci_gem_port = %d\n",
+ __FUNCTION__,
+ p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id, p_sub_term_req->data.svc_port_id);
+
+ if ((BAL_UTIL_OPER_SUB_TERM_ADD != op_type)
+ && (BAL_UTIL_OPER_SUB_TERM_REMOVE != op_type)
+ && (BAL_UTIL_OPER_SUB_TERM_CLEAR != op_type))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Unsupported operation %d for sub_term %u\n",
+ op_type, p_sub_term_req->key.sub_term_id);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ do
+ {
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (p_sub_term_req->key.intf_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ epon_onu_list_entry * p_new_epon_onu_entry;
+ bcmolt_epon_ni_key key;
+ bcmolt_epon_ni_add_link oper;
+
+ key.epon_ni = physical_if_id;
+ BCMOLT_OPER_INIT(&oper, epon_ni, add_link, key);
+
+ if(BAL_UTIL_OPER_SUB_TERM_ADD == op_type)
+ {
+
+ BCMOLT_OPER_PROP_SET(&oper, epon_ni, add_link, mac_address, p_sub_term_req->data.mac_address);
+ BCMOLT_OPER_PROP_SET(&oper, epon_ni, add_link, rate, BCMOLT_EPON_LINK_RATE_TEN_TEN);
+ rc = bcmolt_oper_submit(device_id, &oper.hdr);
+
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to register epon onu epon_ni = %d mac : "_mac_addr_fmt_str" rc = %d (%s), err_text=%s\n",
+ key.epon_ni, _mac_addr_data(p_sub_term_req->data.mac_address), rc, bcmos_strerror(rc),
+ oper.hdr.hdr.err_text);
+ break;
+ }
+ /* add the new epon onu to the epon onu list to follow indications and oam sending */
+ p_new_epon_onu_entry = bcmos_calloc(sizeof(epon_onu_list_entry));
+ if (NULL == p_new_epon_onu_entry)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to allocate the epon onu entry\n");
+ rc = BCM_ERR_NOMEM;
+ break;
+ }
+
+ memcpy(&p_new_epon_onu_entry->bal_onu_key, &p_sub_term_req->key,
+ sizeof(bcmbal_subscriber_terminal_key));
+ p_new_epon_onu_entry->mac_address = p_sub_term_req->data.mac_address;
+ p_new_epon_onu_entry->oam_provision_state = OAM_PROVISION_STATE_IDLE;
+ p_new_epon_onu_entry->waiting_flows_num = 0;
+
+ epon_onu_list_add(p_new_epon_onu_entry);
+ }
+ else
+ {
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_REMOVE,
+ BCM_ERR_OK, BCMOLT_RESULT_SUCCESS,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+
+ epon_onu_list_remove_by_key(&p_sub_term_req->key);
+
+ }
+ } while (0);
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "OUT : going out of %s rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+
+
+ return rc;
+}
+
+
+
+
+
+static bcmos_errno maple_us_sla_configure_epon(bcmbal_flow_cfg *flow_entry, bcmos_mac_address *mac)
+{
+ bcmolt_epon_link_key epon_link_key;
+ bcmolt_epon_link_cfg epon_link_cfg;
+ bcmolt_upstream_bandwidth_distribution us_bw_dist = {};
+
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (flow_entry->data.access_int_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(flow_entry->data.access_int_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ }
+ else
+ {
+
+ epon_link_key.epon_ni = physical_if_id;
+ epon_link_key.mac_address = *mac;
+ BCMOLT_CFG_INIT(&epon_link_cfg, epon_link, epon_link_key);
+
+ us_bw_dist.polling_interval_us = BCMOLT_POLLING_INTERVAL_AUTOMATIC;
+ if (BCMBAL_ATTRIBUTE_PROP_IS_SET(&flow_entry->data.sla, sla, min_rate))
+ {
+ us_bw_dist.min_schedulershaper.bandwidth_Kbps = flow_entry->data.sla.min_rate;
+ }
+ if (BCMBAL_ATTRIBUTE_PROP_IS_SET(&flow_entry->data.sla, sla, max_rate))
+ {
+ us_bw_dist.max_schedulershaper.bandwidth_Kbps = flow_entry->data.sla.max_rate;
+ }
+ else
+ {
+ us_bw_dist.max_schedulershaper.bandwidth_Kbps = 10000000;
+ }
+ us_bw_dist.max_schedulershaper.priority = 7;
+
+ BCMOLT_CFG_PROP_SET(&epon_link_cfg, epon_link, upstream_bandwidth, us_bw_dist);
+ return bcmolt_cfg_set(device_id, &epon_link_cfg.hdr);
+ }
+
+ return rc;
+}
+
+
+
+
+
+
+/**
+ * @brief flow set for EPON
+ *
+ * @param p_flow_req pointer to flow request structure from core
+ * @param op_type ADD, REMOVE or CLEAR
+ * @param p_flow_core local DB flow context passed as a cookie
+ *
+ * @return errno error
+ */
+bcmos_errno mac_util_flow_set_for_epon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ epon_onu_list_entry *p_onu_entry;
+ bcmos_mac_address mac;
+ bcmbal_subscriber_terminal_key key;
+
+
+ key.intf_id = p_flow_req->data.access_int_id;
+ key.sub_term_id = p_flow_req->data.sub_term_id;
+
+ if(NULL != (p_onu_entry = epon_onu_list_find_by_key(&key)))
+ {
+ mac = p_onu_entry->mac_address;
+ }
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "failed to configure flow, "
+ "subscriber terminal if=%d sub-term id = %d was not found - no such device\n",
+ p_flow_req->data.access_int_id, p_flow_req->data.sub_term_id);
+
+ return BCM_ERR_NOENT;
+ }
+
+
+
+ if (BAL_UTIL_OPER_FLOW_ADD == op_type)
+ {
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), "add, context is %p\n", p_flow_context);
+
+ switch (p_onu_entry->oam_provision_state)
+ {
+ case OAM_PROVISION_STATE_IDLE:
+ {
+ p_onu_entry->flow_keys[p_onu_entry->waiting_flows_num++] = p_flow_req->key;
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "add p_onu_entry-> %p, waiting flows: %d context is %p\n",
+ p_onu_entry, p_onu_entry->waiting_flows_num, p_flow_context);
+
+ rc = maple_us_sla_configure_epon(p_flow_req, &mac);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "Unable to configure EPON US SLA (%s)\n", bcmos_strerror(rc));
+
+ break;
+ }
+
+ p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_STARTED;
+
+ bal_oam_configure_traffic(maple_device_from_interface_get(p_flow_req->data.access_int_id),
+ p_flow_req->data.access_int_id,
+ &mac,
+ BCMOS_TRUE,
+ mac_util_configure_traffic_cb, p_flow_context);
+ }
+ break;
+
+
+ case OAM_PROVISION_STATE_STARTED:
+ {
+ if (p_onu_entry->waiting_flows_num < MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC)
+ {
+ p_onu_entry->flow_keys[p_onu_entry->waiting_flows_num++] = p_flow_req->key;
+ }
+ else
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "failed to configure flow for that mac, "
+ "too many flows already waiting for oam configuration\n");
+ rc = BCM_ERR_INSUFFICIENT_LIST_MEM;
+ }
+ }
+ break;
+
+
+ case OAM_PROVISION_STATE_COMPLETED:
+ {
+ mac_util_report_flow_add_success(p_flow_req->key, p_flow_req->data.access_int_id);
+ }
+ break;
+
+
+ case OAM_PROVISION_STATE_FAIL:
+ default:
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "failed to configure oam traffic for that mac,\n"); /* currently no failure indications */
+ }
+ break;
+ }
+ }
+ else /* REMOVE or CLEAR FLOW */
+ {
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "delete p_onu_entry-> %p, waiting flows: %d, provisioned state is %d, context is %p\n",
+ p_onu_entry,
+ p_onu_entry->waiting_flows_num,
+ p_onu_entry->oam_provision_state,
+ p_flow_context);
+
+ switch (p_onu_entry->oam_provision_state)
+ {
+ case OAM_PROVISION_STATE_IDLE:
+ {
+ mac_util_report_flow_remove_success(p_flow_req->key, p_flow_req->data.access_int_id, op_type);
+ }
+ break;
+
+ case OAM_PROVISION_STATE_COMPLETED:
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "calling bal_oam_configure_traffic w/ \"Disable\" state\n");
+
+ bal_oam_configure_traffic(maple_device_from_interface_get(p_flow_req->data.access_int_id),
+ p_flow_req->data.access_int_id,
+ &mac,
+ BCMOS_FALSE,
+ mac_util_unconfigure_traffic_cb,
+ p_flow_context);
+ }
+ break;
+
+ case OAM_PROVISION_STATE_FAIL:
+ case OAM_PROVISION_STATE_STARTED:
+ default:
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id),
+ "failed to unconfigure oam traffic for that mac,\n"); /* currently no failure indications */
+ }
+ break;
+ }
+ }
+
+ return rc;
+}
+
+static void mac_util_configure_traffic_cb(void *context,
+ bcmolt_devid device_id,
+ bcmolt_epon_ni epon_ni,
+ const bcmos_mac_address *mac_address,
+ bcmos_errno result)
+{
+ epon_onu_list_entry *p_onu_entry;
+ int i;
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
+ "configure device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n",
+ device_id, epon_ni, _mac_addr_data(*mac_address), result == BCM_ERR_OK ? "success" : "fail");
+
+
+ if(NULL == (p_onu_entry = epon_onu_list_find_by_mac(mac_address)))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
+ "FAIL - received configure traffic cb for mac that was not configured " _mac_addr_fmt_str "\n",
+ _mac_addr_data(*mac_address));
+ return;
+ }
+
+ if (OAM_PROVISION_STATE_STARTED != p_onu_entry->oam_provision_state)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
+ "FAIL - received configure traffic cb for mac that is in the wrong state (%d)\n",
+ p_onu_entry->oam_provision_state);
+ return;
+ }
+
+ if (result == BCM_ERR_OK)
+ {
+ p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_COMPLETED;
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), "Moved ONU to OAM COMPLETED state\n");
+
+ for (i=0; i<p_onu_entry->waiting_flows_num; i++)
+ {
+ mac_util_report_flow_add_success(p_onu_entry->flow_keys[i], epon_ni);
+ }
+ }
+ else
+ {
+ p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_FAIL;
+ }
+
+ p_onu_entry->waiting_flows_num = 0; /* currently we dont send fail indication */
+}
+
+/** EPON specific traffic unconfigure; Not used for GPON mode */
+static void mac_util_unconfigure_traffic_cb(void *context,
+ bcmolt_devid device_id,
+ bcmolt_epon_ni epon_ni,
+ const bcmos_mac_address *mac_address,
+ bcmos_errno result)
+{
+ flow_inst *p_flow_core = (flow_inst *)(context);
+ epon_onu_list_entry *p_onu_entry;
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni),
+ "unconfigure device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n",
+ device_id,
+ epon_ni,
+ _mac_addr_data(*mac_address),
+ result == BCM_ERR_OK ? "success" : "fail");
+
+
+ /** @todo need to pass on the actual op type (REMOVE or CLEAR) */
+ mac_util_report_flow_remove_success(p_flow_core->current_flow_info.key, epon_ni, BAL_UTIL_OPER_FLOW_REMOVE);
+
+ if(NULL != (p_onu_entry = epon_onu_list_find_by_mac(mac_address)))
+ {
+ p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_IDLE;
+ }
+}
+
+
+
+/**
+ * @brief used for epon oam message handling
+ *
+ * @param device_id bcm dev id
+ * @param p_msg oam msg pointer
+ */
+void bal_proxy_rx_cb_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmolt_proxy_rx *proxy_rx = (bcmolt_proxy_rx *)p_msg;
+
+ bcmolt_user_appl_eon_process_rx(device_id, proxy_rx);
+ bcmolt_user_appl_epon_oam_handle_rx(device_id, proxy_rx, bal_oam_proxy_rx_cb);
+
+ /** @note the free of p_msg is done in caller function */
+}
+
+
+/**
+ * @brief init for epon oam and eon
+ *
+ */
+static void mac_util_init_oam_for_epon (void)
+{
+ bcmolt_user_appl_epon_oam_init();
+ bcmolt_user_appl_eon_init();
+}
+
+
+
+
+static void epon_onu_list_add(epon_onu_list_entry *epon_onu_entry)
+{
+ TAILQ_INSERT_HEAD(&epon_onu_list, epon_onu_entry, next);
+ return;
+}
+
+static void epon_onu_list_remove_by_key(bcmbal_subscriber_terminal_key *key)
+{
+ epon_onu_list_entry *p_onu_entry = NULL;
+
+ if(NULL != (p_onu_entry = epon_onu_list_find_by_key(key)))
+ {
+ TAILQ_REMOVE(&epon_onu_list, p_onu_entry, next);
+ bcmos_free(p_onu_entry);
+ }
+
+ return;
+}
+
+static epon_onu_list_entry *epon_onu_list_find_by_mac(const bcmos_mac_address *mac_address)
+{
+ epon_onu_list_entry *p_onu_entry = NULL;
+ epon_onu_list_entry *current_onu_entry;
+
+ TAILQ_FOREACH(current_onu_entry, &epon_onu_list, next)
+ {
+ if (memcmp(¤t_onu_entry->mac_address, mac_address, sizeof(bcmos_mac_address))==0)
+ {
+ p_onu_entry = current_onu_entry;
+ break;
+ }
+ }
+
+ return p_onu_entry;
+}
+
+static epon_onu_list_entry *epon_onu_list_find_by_key(bcmbal_subscriber_terminal_key *key)
+{
+ epon_onu_list_entry *p_onu_entry = NULL;
+ epon_onu_list_entry *current_onu_entry;
+
+ TAILQ_FOREACH(current_onu_entry, &epon_onu_list, next)
+ {
+ if ((current_onu_entry->bal_onu_key.intf_id == key->intf_id) &&
+ (current_onu_entry->bal_onu_key.sub_term_id == key->sub_term_id))
+ {
+ p_onu_entry = current_onu_entry;
+ break;
+ }
+ }
+
+ return p_onu_entry;
+}
+#endif /* BAL_EPON_EXCLUDE */
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util_epon.h b/bal_release/src/core/util/mac/bal_mac_util_epon.h
new file mode 100644
index 0000000..68da0df
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_epon.h
@@ -0,0 +1,109 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_epon.h
+ *
+ * @brief mac util interfaces definition used by Bal Core, for EPON
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+
+/* Temporarily exclude some code to get this module compiling again - we should get rid of this ASAP */
+#define BAL_EPON_EXCLUDE 0
+
+#if BAL_EPON_EXCLUDE
+bcmos_errno mac_util_handle_all_olt_ind_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+bcmos_errno mac_util_register_for_epon_auto_indications(struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id);
+#endif /* BAL_EPON_EXCLUDE */
+
+bcmos_errno mac_util_access_terminal_set_for_epon_8_tdma(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_4_tdma(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_16_1g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_8_1g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_4_1g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_8_10g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_4_10g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_access_terminal_set_for_epon_2_10g(
+ acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term op_type,
+ bcmolt_devid device_id);
+
+bcmos_errno mac_util_interface_set_for_epon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type);
+
+#if BAL_EPON_EXCLUDE
+bcmos_errno mac_util_validate_subscriber_terminal_info_for_epon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req);
+
+bcmos_errno mac_util_subscriber_terminal_set_for_epon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery);
+
+bcmos_errno mac_util_flow_set_for_epon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core);
+
+void bal_proxy_rx_cb_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg);
+#endif /* BAL_EPON_EXCLUDE */
+
+/*@}*/
+
diff --git a/bal_release/src/core/util/mac/bal_mac_util_gpon.c b/bal_release/src/core/util/mac/bal_mac_util_gpon.c
new file mode 100644
index 0000000..b08efd6
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_gpon.c
@@ -0,0 +1,1961 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_gpon.c
+ *
+ * @brief mac util interfaces definition used by Bal Core, for GPON
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+#include <bal_mac_util_common_itu_pon.h>
+
+static bcmos_errno mac_util_indication_handle_for_gpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_indication_handle_for_gpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_indication_handle_for_gpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_indication_handle_for_gpon_gem_port (bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+/** @brief array stores the list of GPON related auto indications from Maple to subscribe */
+static mac_util_ind_obj_and_handlers mac_util_gpon_ind_handlers[] =
+{
+ {BCMOLT_OBJ_ID_GPON_NI, "BCMOLT_OBJ_ID_GPON_NI", mac_util_indication_handle_for_gpon_ni},
+ {BCMOLT_OBJ_ID_GPON_ONU, "BCMOLT_OBJ_ID_GPON_ONU", mac_util_indication_handle_for_gpon_onu},
+ {BCMOLT_OBJ_ID_GPON_ALLOC, "BCMOLT_OBJ_ID_GPON_ALLOC", mac_util_indication_handle_for_gpon_alloc_id},
+ {BCMOLT_OBJ_ID_GPON_GEM_PORT, "BCMOLT_OBJ_ID_GPON_GEM_PORT", mac_util_indication_handle_for_gpon_gem_port}
+};
+
+
+/**
+ * @brief Map bal GPON transceiver type to bcm68620 transceiver type
+ */
+static bcmolt_trx_type mac_gpon_bal_trx_type2bcm68620_trx_type(bcmbal_trx_type bal_trx_type, bcmbal_intf_id intf_id)
+{
+ bcmolt_trx_type trx_type = BCMOLT_TRX_TYPE__NUM_OF;
+
+ switch (bal_trx_type)
+ {
+ case BCMBAL_TRX_TYPE_GPON_SPS_43_48:
+ trx_type = BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013;
+ break;
+ case BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321:
+ trx_type = BCMOLT_TRX_TYPE_SOG_4321_PSGB;
+ break;
+ case BCMBAL_TRX_TYPE_GPON_LTE_3680_M:
+ trx_type = BCMOLT_TRX_TYPE_LTE_3680_M;
+ break;
+ case BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS:
+ trx_type = BCMOLT_TRX_TYPE_SOURCE_PHOTONICS;
+ break;
+ case BCMBAL_TRX_TYPE_GPON_LTE_3680_P:
+ trx_type = BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS;
+ break;
+ default:
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_id), "Invalid trx_type %d\n", bal_trx_type);
+ }
+ return trx_type;
+}
+
+
+
+
+/**
+ * @brief all the maple indication handlers for gpon
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ */
+bcmos_errno mac_util_handle_all_olt_ind_for_gpon (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ BCM_LOG(DEBUG, log_id_mac_util,
+ "mac_util_indication_cb received indication obj=%d/%s group=%d subgroup=%d\n",
+ p_msg->obj_type, mac_util_indication_get_obj_type_str(p_msg->obj_type, mac_util_gpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_gpon_ind_handlers)),
+ p_msg->group, p_msg->subgroup);
+
+ return mac_util_handle_indication(device_id, p_msg, mac_util_gpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_gpon_ind_handlers));
+}
+
+/**
+ * @brief Handler function for Maple auto indications for GPON NI
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_gpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+
+ do
+ {
+
+ /* PON activation */
+ if (BCMOLT_GPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_gpon_ni_state_change_completed * p_ind = (bcmolt_gpon_ni_state_change_completed*)p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), "Pon if %d is %s.\n", logical_pon,
+ BCMOLT_PON_STATE_ACTIVE_WORKING == p_ind->data.new_state ? "up" : "down");
+
+ /* if we got something from MAC HW, then it has to be PON interface */
+ mac_util_report_if_event(logical_pon, BCMBAL_INTF_TYPE_PON, p_msg->err,
+ p_ind->data.result, p_ind->data.new_state);
+
+ }
+ else if(BCMOLT_GPON_NI_AUTO_CFG_ID_ONU_DISCOVERED == p_msg->subgroup)
+ {
+ bcmolt_gpon_ni_onu_discovered *p_ind =
+ (bcmolt_gpon_ni_onu_discovered *)p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Pon if %d (ONUID:%d) found ONU serial number "
+ "%c%c%c%c%d%d%d%d%d%d%d%d\n",
+ logical_pon,
+ p_ind->data.onu_id,
+ p_ind->data.serial_number.vendor_id[0],
+ p_ind->data.serial_number.vendor_id[1],
+ p_ind->data.serial_number.vendor_id[2],
+ p_ind->data.serial_number.vendor_id[3],
+ p_ind->data.serial_number.vendor_specific[0]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[0] & 0x0f,
+ p_ind->data.serial_number.vendor_specific[1]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[1] & 0x0f,
+ p_ind->data.serial_number.vendor_specific[2]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[2] & 0x0f,
+ p_ind->data.serial_number.vendor_specific[3]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[3] & 0x0f
+ );
+
+ bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ mac_util_report_sub_term_event(logical_pon,
+ p_ind->data.onu_id,
+ &p_ind->data.serial_number,
+ BAL_UTIL_OPER_SUB_TERM_DISCOVERY,
+ p_msg->err, BCMOLT_RESULT_SUCCESS,
+ BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ }
+ else
+ {
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_gpon_ni_key *p_pon_key = &(((bcmolt_gpon_ni_state_change_completed*)p_msg)->key);
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj Gpon_NI group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ }
+
+ }
+ while(0);
+ return rc;
+}
+
+
+
+/**
+ * @brief Handler function for Maple auto indications for GPON ONU
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_gpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_gpon_onu_key *p_gpon_onu_key = &(((bcmolt_gpon_onu_onu_activation_completed*)p_msg)->key);
+
+ do
+ {
+ if (BCMOLT_GPON_ONU_AUTO_CFG_ID_ONU_ACTIVATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_gpon_onu_onu_activation_completed *p_ind = (bcmolt_gpon_onu_onu_activation_completed*) p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_ind->key.pon_ni),
+ "sub_term %d (PON%d) activation indication (%s)\n",
+ p_ind->key.onu_id,
+ p_ind->key.pon_ni,
+ bcmos_strerror(p_msg->err));
+
+ mac_util_report_sub_term_event(logical_pon,
+ p_ind->key.onu_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_ADD,
+ p_msg->err, p_ind->data.status,
+ p_ind->data.fail_reason, BCMBAL_INVALID_TUNNEL_ID);
+
+ }
+ else if(BCMOLT_GPON_ONU_AUTO_CFG_ID_ONU_DEACTIVATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_gpon_onu_onu_deactivation_completed *p_ind = (bcmolt_gpon_onu_onu_deactivation_completed*) p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "sub_term %d (PON%d) deactivation indication (%s)\n",
+ p_ind->key.onu_id,
+ logical_pon,
+ bcmos_strerror(p_msg->err));
+ mac_util_report_sub_term_event(logical_pon,
+ p_ind->key.onu_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_REMOVE,
+ p_msg->err, p_ind->data.status,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ }
+ else
+ {
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_gpon_onu_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_gpon_onu_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj GPON_ONU group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ break;
+ }
+
+ rc = mac_util_update_flows_w_sub_term_update(logical_pon, p_gpon_onu_key->onu_id, maple_gpon_mac_check_gem_port_id, maple_gpon_mac_get_alloc_id_config);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to update related flows pon_id = %d onu_id = %d (%s)\n", logical_pon, p_gpon_onu_key->onu_id, bcmos_strerror(rc));
+ break;
+ }
+
+ }
+ while(0);
+ return rc;
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for GPON Alloc Id
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_gpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+ tm_sched_inst* p_tm_sched_inst = NULL;
+ do
+ {
+ if (BCMOLT_GPON_ALLOC_AUTO_CFG_ID_CONFIGURATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_gpon_alloc_configuration_completed *p_ind = (bcmolt_gpon_alloc_configuration_completed*) p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ /* Find tn_mode inst owned by that alloc_id and ni */
+ p_tm_sched_inst = tm_sched_find_agg_port_node(logical_pon, p_ind->key.alloc_id);
+ if (NULL == p_tm_sched_inst )
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to find tm sched owned by that agg port (intf %d id %d)\n", logical_pon,p_ind->key.alloc_id);
+ rc = BCM_ERR_NOENT;
+ break;
+ }
+ /*the tm owned by that alloc found, update it with the ind*/
+ mac_util_report_tm_sched_set_indication(p_tm_sched_inst->req_tm_sched_info.key ,p_msg->err, p_ind->data.status);
+ }
+ else
+ {
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_gpon_alloc_key *p_pon_key = &(((bcmolt_gpon_alloc_configuration_completed*)p_msg)->key);
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj GPON_ALLOC group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ }
+ }while (0);
+ return rc;
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for GPON GEM Port
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_gpon_gem_port (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+ flow_list_entry *p_current_entry = NULL;
+ void *p_rsc_mgr_curr_entry = NULL;
+ void *p_rsc_mgr_next_entry = NULL;
+
+ do
+ {
+
+ if (BCMOLT_GPON_GEM_PORT_AUTO_CFG_ID_CONFIGURATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_gpon_gem_port_configuration_completed *p_ind =
+ (bcmolt_gpon_gem_port_configuration_completed *) p_msg;
+
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ /* Find all entries in flows list matching the gem port id and pon ni */
+ /* use safe walk here because an entry can be removed from list during the walk */
+ /* get first */
+ p_current_entry = _mac_util_db_flow_get_next_w_gem (logical_pon, p_ind->key.gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ while (NULL != p_current_entry)
+ {
+ /** @note For now this assumes that there is only one op type (add or remove) ,
+ * that all the flows in an onu are waiting for. We can not have flows waiting on same
+ * gem for multiple op types, because Maple does not allow multiple configs with
+ * different op types at the same time.
+ */
+ /* update gem port complete configuration indication received */
+ p_current_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
+ /* check if should send flow configuration indication complete to bal core */
+ rc = check_send_flow_bal_ind_msg(p_current_entry, p_msg->err, p_ind->data.status);
+
+ /* any DB cleanup for error should be triggered by Core fsm
+ * (mac util should not cleanup on its own)
+ * */
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Failed to send flow configured ind: Error %s, gem port id = %d, pon ni = %d\n",
+ bcmos_strerror(rc), p_ind->key.gem_port_id, logical_pon);
+ /* don't break, but continue to check if more flows use the same gem port id */
+ }
+
+ /* get next */
+ p_current_entry = _mac_util_db_flow_get_next_w_gem (logical_pon, p_ind->key.gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
+ }
+ }
+ else
+ {
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_gpon_gem_port_key *p_pon_key = &(((bcmolt_gpon_gem_port_configuration_completed*)p_msg)->key);
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj GPON_GEM_PORT group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ }
+
+ }
+ while(0);
+ return rc;
+}
+
+/**
+ * @brief Maple auto indication register for specific GPON based indications
+ *
+ * @param p_rx_cfg handler config structure
+ * @param device_id specific device id (for multiple devices support)
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_register_for_gpon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id)
+{
+ return _mac_util_register_for_auto_indications (p_rx_cfg, mac_util_gpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_gpon_ind_handlers), device_id);
+}
+
+/*****************************************************************************/
+/**
+ * @brief Map iwf_mode to bcmolt_iwf_mode
+ *
+ * @param bal_iwf_mode BAL iwfmode
+ * @return bcm68620 iwf mode
+ */
+static bcmolt_iwf_mode bal_iwf_mode2iwf_mode(bcmbal_iwf_mode bal_iwf_mode)
+{
+ bcmolt_iwf_mode iwf_mode = BCMOLT_IWF_MODE__NUM_OF;
+ switch (bal_iwf_mode)
+ {
+ case BCMBAL_IWF_MODE_DIRECT_MAPPING:
+ iwf_mode = BCMOLT_IWF_MODE_DIRECT_MAPPING_MODE;
+ break;
+ case BCMBAL_IWF_MODE_PER_FLOW:
+ iwf_mode = BCMOLT_IWF_MODE_PER_FLOW_MODE;
+ break;
+ default:
+ BCM_LOG(ERROR, log_id_mac_util, "Invalid iwf_mode %d\n", bal_iwf_mode);
+ }
+ return iwf_mode;
+}
+
+static bcmos_errno mac_util_access_terminal_set_for_gpon (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_system_mode system_mode, bcmolt_devid device_id)
+{
+ bcmolt_device_key key = {};
+ bcmolt_device_nni_speed nni_speed_cfg;
+ bcmolt_device_cfg dev_cfg;
+ bcmolt_iwf_mode iwf_mode;
+ uint32_t logical_pon;
+
+ if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&(p_acc_term->api_req_acc_term_obj_info), access_terminal, iwf_mode))
+ {
+ iwf_mode = bal_iwf_mode2iwf_mode(p_acc_term->api_req_acc_term_obj_info.data.iwf_mode);
+ }
+ else
+ {
+ iwf_mode = BCMOLT_IWF_MODE_DIRECT_MAPPING_MODE;
+ }
+
+ BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon)
+ {
+ mac_util_topo_pon_context *topo_context, *old_topo_context;
+
+ old_topo_context = bcm_topo_pon_get_context(logical_pon, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
+ if (old_topo_context)
+ bcmos_free(old_topo_context);
+
+ topo_context = bcmos_calloc(sizeof(*topo_context));
+ topo_context->iwf_mode = iwf_mode;
+ bcm_topo_pon_set_context(logical_pon, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL, topo_context);
+ }
+
+ BCMOLT_CFG_INIT(&dev_cfg, device, key);
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, acc_term_connectivity.devices[device_id].system_mode);
+
+#ifdef QAX_SWITCH
+ /* until speed is configurable through topology settings hardcode it based on switch type */
+ BCM_LOG(INFO, log_id_mac_util, "nni speed is: 10G\n");
+ nni_speed_cfg.first_half = BCMOLT_NNI_SPEED_GBPS_10;
+ nni_speed_cfg.second_half = BCMOLT_NNI_SPEED_GBPS_10;
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, nni_speed, nni_speed_cfg);
+#endif
+
+ return bcmolt_cfg_set(device_id, &dev_cfg.hdr);
+}
+
+/**
+ * @brief access terminal set for gpon_16
+ */
+bcmos_errno mac_util_access_terminal_set_for_gpon_16 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
+{
+ bcmos_errno rc;
+ rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+ rc = mac_util_access_terminal_set_for_gpon(p_acc_term, op_type, BCMOLT_SYSTEM_MODE_GPON__16_X, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+ return maple_access_terminal_connect_common(device_id);
+
+}
+
+/**
+ * @brief access terminal set for gpon_8
+ */
+bcmos_errno mac_util_access_terminal_set_for_gpon_8 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
+{
+ bcmos_errno rc;
+
+ rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+ rc = mac_util_access_terminal_set_for_gpon(p_acc_term, op_type, BCMOLT_SYSTEM_MODE_GPON__8_X, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+ return maple_access_terminal_connect_common(device_id);
+}
+
+/**
+ * @brief post access terminal up configurations on Maple
+ */
+bcmos_errno mac_util_access_terminal_post_indication_set_for_gpon(bcmolt_devid device_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_devid dummy;
+ uint32_t physical_if_id;
+ uint32_t logical_pon = BCM_TOPO_PON_INVALID;
+ bcmolt_gpon_ni_key ni_key = {};
+ bcmolt_gpon_ni_cfg ni_cfg = {};
+ bcmolt_gpon_sn_acquisition sn_acquisition_cfg = {};
+ bcmolt_gpon_ni_auto_cfg gpon_ni_auto_cfg = {}; /* main auto cfg api struct */
+
+ /* configure one time settings for all the interfaces on this device */
+ BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon)
+ {
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (logical_pon, &dummy, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ ni_key.pon_ni = physical_if_id;
+
+
+ /* Set the SN acquisition mode to enable */
+ BCMOLT_CFG_INIT(&ni_cfg, gpon_ni, ni_key);
+
+ sn_acquisition_cfg.control = BCMOLT_CONTROL_STATE_ENABLE;
+ sn_acquisition_cfg.interval = 5000;
+ sn_acquisition_cfg.onu_post_discovery_mode = BCMOLT_ONU_POST_DISCOVERY_MODE_NONE;
+
+ BCMOLT_CFG_PROP_SET(&ni_cfg, gpon_ni, sn_acquisition, sn_acquisition_cfg);
+
+ rc = bcmolt_cfg_set(device_id, &ni_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Failed to set sn acquisition configuration (%s), err_text=%s)\n",
+ bcmos_strerror(rc), ni_cfg.hdr.hdr.err_text);
+ break;
+ }
+
+
+ /* turn off the auto indication messages for gpon_ni.serial_number_acquisition_cycle_start */
+ BCMOLT_AUTO_CFG_INIT(&gpon_ni_auto_cfg, gpon_ni, ni_key);
+ BCMOLT_AUTO_CFG_PROP_SET(&gpon_ni_auto_cfg, gpon_ni, serial_number_acquisition_cycle_start, BCMOS_FALSE);
+ rc = bcmolt_auto_cfg_set(device_id, &gpon_ni_auto_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "bcmolt_auto_cfg_set for gpon_ni.serial_number_acquisition_cycle_start, Failed (%s), err_text=%s)\n",
+ bcmos_strerror(rc), gpon_ni_auto_cfg.hdr.hdr.err_text);
+
+ /* ignore any error, just continue anyway */
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * @brief Command Set setup routine for interface up to mac application for GPON
+ *
+ * This routine is called by if_fsm in the BAL core to initialize the command
+ * set to up the interface of the mac application. The cmdset actually
+ * consists of two commands, one is to send the if up request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param op_type Operation type on access terminal/interface instance
+ *
+ * @return bcmos_errno
+ *
+ */
+bcmos_errno mac_util_interface_set_for_gpon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmbal_interface_cfg *p_interface_req = &(p_interface_inst->api_req_int_obj_info);
+ bcmbal_interface_key intf_key = p_interface_req->key;
+ mac_util_topo_pon_context *topo_context;
+
+ do
+ {
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (intf_key.intf_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+
+ bcmolt_gpon_ni_set_pon_state oper_ni;
+ bcmolt_gpon_ni_key ni_key = { .pon_ni = physical_if_id };
+ bcmolt_gpon_trx_cfg cfg = {};
+ bcmolt_gpon_trx_key trx_key = { .pon_ni = physical_if_id };
+ bcmolt_trx_type trx_type;
+ bcmolt_gpon_iwf_key iwf_key = { .pon_ni = physical_if_id };
+ bcmolt_gpon_iwf_cfg iwf_cfg = {};
+ bcmolt_mac_table_configuration mac_table_configuration = {};
+
+ if (BAL_UTIL_OPER_IF_UP == op_type)
+ {
+
+ /* set the pon_ni transceiver configuration */
+ BCMOLT_CFG_INIT(&cfg, gpon_trx, trx_key);
+
+ /* If the user didn't specify a transceiver, then use the default */
+ if (BCMOS_TRUE != BCMBAL_CFG_PROP_IS_SET(p_interface_req, interface, transceiver_type))
+ {
+ /* The user didn't choose a transceiver type, so override it here
+ * with the default value for GPON
+ */
+ BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_GPON);
+ }
+
+ /* Set the (default or chosen) transceiver configuration into the MAC device */
+ trx_type = mac_gpon_bal_trx_type2bcm68620_trx_type(p_interface_req->data.transceiver_type, intf_key.intf_id);
+ BCMOLT_CFG_PROP_SET(&cfg, gpon_trx, transceiver_type, trx_type);
+
+ rc = bcmolt_cfg_set(device_id, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to set trx configuration (%s), err_text=%s\n", bcmos_strerror(rc), cfg.hdr.hdr.err_text);
+ break;
+ }
+
+
+ /* Configure pon_ni interworking and mac table configuration based on the system global interworking mode
+ *
+ * We only have to change the mode if the user has chosen per-flow, because direct mode is the default
+ * iwf mode in MAPLE
+ */
+ topo_context = bcm_topo_pon_get_context(intf_key.intf_id, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
+ if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
+ {
+ /* set the iwf configuration */
+ BCMOLT_CFG_INIT(&iwf_cfg, gpon_iwf, iwf_key);
+ BCMOLT_CFG_PROP_SET(&iwf_cfg, gpon_iwf, iwf_mode, BCMOLT_IWF_MODE_PER_FLOW_MODE);
+ /* set the mac table configuration */
+ mac_table_configuration.aging_time = 10000;
+ mac_table_configuration.automatic_mac_move = BCMOLT_CONTROL_STATE_DISABLE;
+ mac_table_configuration.automatic_static_mode = BCMOLT_CONTROL_STATE_DISABLE;
+ mac_table_configuration.default_flow_id = 0;
+ mac_table_configuration.learning_mode = BCMOLT_MAC_TABLE_LEARNING_MODE_NORMAL;
+ mac_table_configuration.miss_fallback = BCMOLT_MAC_TABLE_MISS_FALLBACK_DROP;
+ mac_table_configuration.automatic_mac_learning = BCMOLT_CONTROL_STATE_ENABLE;
+ mac_table_configuration.automatic_mac_aging = BCMOLT_CONTROL_STATE_ENABLE;
+ BCMOLT_CFG_PROP_SET(&iwf_cfg, gpon_iwf, mac_table_configuration, mac_table_configuration);
+
+ rc = bcmolt_cfg_set(device_id, &iwf_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to set iwf / mac table configuration (%s), err_text=%s)\n",
+ bcmos_strerror(rc), iwf_cfg.hdr.hdr.err_text);
+ break;
+ }
+ }
+ }
+
+
+ /* invoke the pon_ni state change to the requested state */
+ BCMOLT_OPER_INIT(&oper_ni, gpon_ni, set_pon_state, ni_key);
+ BCMOLT_OPER_PROP_SET(&oper_ni, gpon_ni, set_pon_state, pon_state,
+ (BAL_UTIL_OPER_IF_UP == op_type) ?
+ BCMOLT_PON_OPERATION_ACTIVE_WORKING : BCMOLT_PON_OPERATION_INACTIVE);
+ rc = bcmolt_oper_submit(device_id, &oper_ni.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to %s (submit) pon interface (%s), err_text=%s\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
+ bcmos_strerror(rc), oper_ni.hdr.hdr.err_text);
+ }
+
+ } while (0);
+
+ if (BCM_ERR_OK == rc)
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Submitted INTERFACE-%s operation for IF %d\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "UP" : "DOWN",
+ intf_key.intf_id);
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief maple_mac_ds_iwf_cfg
+ *
+ * This routine is used to configure the relevant downstream ingress and egress iwf at the device
+ *
+ * @param p_flow Pointer to the flow info
+ * @param per_flow_mode_vlan_id vlan id for GEM port mapping in per flow mode
+ * @param is_pbit_enabled Flag indicating whether or not to resolve pbits to GEM IDs
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_mac_ds_iwf_cfg(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bcmos_bool is_pbit_enabled)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_iwf_ds_ingress_flow_key in_key = {};
+ bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg = {};
+ bcmolt_gpon_iwf_ds_egress_flow_key egr_key = {};
+ bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+
+ do
+ {
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ /* configure the new ds ingress flow */
+ in_key.pon_ni = physical_if_id;
+ in_key.vlan_id = per_flow_mode_vlan_id;
+ BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
+ if (BCMOS_TRUE == p_flow->data.resolve_mac)
+ {
+ /* mapping method */
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_method,
+ BCMOLT_VLAN_TO_FLOW_MAPPING_METHOD_MACPLUSVID);
+ }
+ else
+ {
+ /* mapping method */
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_method,
+ BCMOLT_VLAN_TO_FLOW_MAPPING_METHOD_VID);
+ }
+
+ /* mapping tag */
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_tag,
+ BCMOLT_MAPPING_TAG_METHOD_OUTER_VID);
+ BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, vlan_action, BCMOLT_DS_VLAN_ACTION_TRANSPARENT);
+
+ rc = bcmolt_cfg_set(device_id, &in_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to configure ingress flow pon_ni = %d vlan_id = %d rc = %s (%d), err_text=%s\n",
+ in_key.pon_ni,
+ in_key.vlan_id,
+ bcmos_strerror(rc),
+ rc,
+ in_cfg.hdr.hdr.err_text);
+ break;
+ }
+
+
+ /* configure the new ds egress flow */
+ egr_key.pon_ni = physical_if_id;
+ egr_key.flow_id = p_flow->data.svc_port_id;
+
+ /* Configure DS egress handling: flow -> GEM */
+ BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
+ BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, gem_port, p_flow->data.svc_port_id);
+ BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, pbit_control, is_pbit_enabled);
+
+ rc = bcmolt_cfg_set(device_id, &egr_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to configure egress flow pon_ni = %d flow_id = %d rc = %s (%d), err_text=%s\n",
+ egr_key.pon_ni,
+ egr_key.flow_id,
+ bcmos_strerror(rc),
+ rc,
+ egr_cfg.hdr.hdr.err_text);
+ }
+
+ } while (0);
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "going out of %s rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ return rc;
+}
+
+
+/**
+ * @brief maple_mac_ds_iwf_cfg_remove
+ *
+ * This routine is used to remove configuration from Maple of the relevant downstream ingress and egress iwf
+ *
+ * @param p_flow Pointer to the flow info
+ * @param per_flow_mode_vlan_id vlan id for per flow mode
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_mac_ds_iwf_cfg_remove(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_iwf_ds_ingress_flow_key in_key = {};
+ bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg = {};
+ bcmolt_gpon_iwf_ds_egress_flow_key egr_key = {};
+ bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ do
+ {
+ /* config clear ds ingress flow */
+ rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ in_key.pon_ni = physical_if_id;
+ in_key.vlan_id = per_flow_mode_vlan_id;
+ BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
+
+ rc = bcmolt_cfg_clear(device_id, &in_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to Clear ingress flow pon_ni = %d vlan_id = %d rc = %s (%d)\n",
+ in_key.pon_ni,
+ in_key.vlan_id,
+ bcmos_strerror(rc),
+ rc);
+ break;
+ }
+
+
+ /* config clear ds egress flow */
+ egr_key.pon_ni = physical_if_id;
+ egr_key.flow_id = p_flow->data.svc_port_id;
+
+ /* Configure DS egress handling: flow -> GEM */
+ BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
+
+ rc = bcmolt_cfg_clear(device_id, &egr_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to Clear egress flow pon_ni = %d flow_id = %d rc = %s (%d)\n",
+ egr_key.pon_ni,
+ egr_key.flow_id,
+ bcmos_strerror(rc),
+ rc);
+ }
+
+ } while (0);
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s: config clear: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+
+ return rc;
+}
+
+
+/**
+ * @brief maple_mac_us_iwf_cfg
+ *
+ * This routine is used to configure the relevant upstream iwf at the device
+ *
+ * @param p_flow A pointer to a flow object
+ *
+ * @param pbit A pbit value being configured for the specified flow
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_mac_us_iwf_cfg(bcmbal_flow_cfg *p_flow, uint8_t pbit)
+{
+ bcmos_errno rc = BCM_ERR_PARM;
+ bcmolt_gpon_iwf_us_flow_key us_key = {};
+ bcmolt_gpon_iwf_us_flow_cfg us_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ }
+ else
+ {
+ /* configure the related iwf us flow */
+ us_key.pon_ni = physical_if_id;
+ us_key.gem_port_id = p_flow->data.svc_port_id;
+ BCMOLT_CFG_INIT(&us_cfg, gpon_iwf_us_flow, us_key);
+ BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, flow_id, p_flow->data.svc_port_id);
+ if (BCMOS_TRUE == p_flow->data.resolve_mac)
+ {
+ BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, mac_learning, BCMOS_TRUE);
+ }
+ else
+ {
+ BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, mac_learning, BCMOS_FALSE);
+ }
+ BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, vlan_action, BCMOLT_US_VLAN_ACTION_TRANSPARENT);
+
+ rc = bcmolt_cfg_set(device_id, &us_cfg.hdr);
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s FAILED, rc = %s (%d), err_text = %s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc, us_cfg.hdr.hdr.err_text);
+ }
+ return rc;
+}
+
+
+/**
+ * @brief maple_mac_us_iwf_cfg_remove
+ *
+ * This routine is used to remove configuration from Maple of the relevant upstream iwf
+ *
+ * @param p_flow A pointer to a flow object
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno maple_mac_us_iwf_cfg_remove(bcmbal_flow_cfg *p_flow)
+{
+ bcmos_errno rc = BCM_ERR_PARM;
+ bcmolt_gpon_iwf_us_flow_key us_key = {};
+ bcmolt_gpon_iwf_us_flow_cfg us_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ /* configure the related iwf us flow */
+ rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ return rc;
+ }
+
+ us_key.pon_ni = physical_if_id;
+ us_key.gem_port_id = p_flow->data.svc_port_id;
+ BCMOLT_CFG_INIT(&us_cfg, gpon_iwf_us_flow, us_key);
+
+ rc = bcmolt_cfg_clear(device_id, &us_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
+ "%s FAILED, rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief mac_util_validate_subscriber_terminal_info_for_gpon
+ *
+ * This routine is used to validate all input attributes required for a sub term setting
+ * received from core for GPON
+ *
+ * @param p_sub_term_req A pointer to a subscriber terminal object
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_validate_subscriber_terminal_info_for_gpon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req)
+{
+ if(BCMBAL_STATE_UP == p_sub_term_req->data.admin_state)
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET (p_sub_term_req, subscriber_terminal, serial_number))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Serial number is a mandatory parameter for a gpon subscriber terminal, and it is not set\n");
+ return BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+
+ if (!BCMBAL_CFG_PROP_IS_SET(p_sub_term_req, subscriber_terminal, password))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Password is a mandatory parameter for a gpon subscriber terminal, and it is not set\n");
+ return BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief Command Set setup routine for subscriber terminal connect to mac application for GPON
+ *
+ * This routine is called by sub_term_fsm in the BAL core to initialize the command
+ * set to connect the subscriber terminal of the mac application. The cmdset actually
+ * consists of two commands, one is to send the sub_term request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_sub_term_inst A pointer to a subscriber terminal instance
+ * @param op_type Type of operation being performed on the subscriber terminal instance
+ * @param is_post_discovery Used for ADD, indicates if this is a request after a ONU discovery
+ *
+ * @return bcmos_errno
+ *
+ * @note we configure Maple for ONU in 2 stages:
+ * \li Stage 1: do cfg_set with the serial num, password, omci port, as part of first sub_term_set from Core
+ * \li Stage 2: set the ONU state to ACTIVE using oper_submit, as part of second sub_term_set from Core (after
+ * receiving a Discovery indication)
+ */
+bcmos_errno mac_util_subscriber_terminal_set_for_gpon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
+
+ do
+ {
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (p_sub_term_req->key.intf_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ bcmolt_gpon_onu_cfg cfg = {};
+ bcmolt_gpon_onu_cfg onu_cfg_get = {};
+ bcmolt_gpon_onu_set_onu_state oper = {};
+ bcmolt_gpon_onu_key key = {};
+ bcmolt_onu_operation new_onu_state;
+ bcmolt_gpon_onu_auto_cfg gpon_onu_auto_cfg = {}; /* main auto cfg api struct */
+
+ /* set the onu key - set it to the physical if id */
+ key.pon_ni = physical_if_id;
+ key.onu_id = p_sub_term_req->key.sub_term_id;
+
+ /* set the onu key */
+ BCMOLT_CFG_INIT(&cfg, gpon_onu, key);
+
+ /* invoke onu state change operation to the new state */
+ BCMOLT_OPER_INIT(&oper, gpon_onu, set_onu_state, key);
+
+ if(BAL_UTIL_OPER_SUB_TERM_CLEAR == op_type)
+ {
+ /* Delete the configuration of the ONU */
+ rc = bcmolt_cfg_clear(device_id, &cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to clear onu configuration(%s)\n",
+ bcmos_strerror(rc));
+ }
+
+ /* No indication from Maple will result from the clear operation
+ * so fake it here
+ */
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_CLEAR,
+ rc, rc,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+
+ /* No further processing is required for the CLEAR operation */
+ break;
+
+
+ }
+ else if(BAL_UTIL_OPER_SUB_TERM_ADD == op_type)
+ {
+ /* first do a get, to see if onu is in active state already */
+ BCMOLT_CFG_INIT(&onu_cfg_get, gpon_onu, key);
+ BCMOLT_CFG_PROP_GET(&onu_cfg_get, gpon_onu, onu_state);
+ rc = bcmolt_cfg_get(device_id, &onu_cfg_get.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to get onu configuration(%s), err_text=%s, ... continue to configure\n",
+ bcmos_strerror(rc), onu_cfg_get.hdr.hdr.err_text);
+
+ /* don't break, but continue with the set anyways */
+ }
+ else
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s: ONU state = %d, [pon_ni=%d, onu_id=%d], BEFORE doing cfg_set on Maple\n",
+ __FUNCTION__, onu_cfg_get.data.onu_state, onu_cfg_get.key.pon_ni, onu_cfg_get.key.onu_id);
+ }
+
+
+ if ((BCM_ERR_OK == rc) && (BCMOLT_ONU_STATE_ACTIVE == onu_cfg_get.data.onu_state))
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s: ONU already in active state during ADD. Skipping further config\n",
+ __FUNCTION__);
+
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_ADD,
+ rc, rc,
+ BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ break;
+ }
+
+
+ /* set the sn & password only if it being configured for the first time */
+ if (BCMOS_FALSE == is_post_discovery)
+ {
+ BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, serial_number,
+ *((bcmolt_serial_number *)&p_sub_term_req->data.serial_number));
+
+ BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, password,
+ *((bcmolt_arr_u8_10 *)&p_sub_term_req->data.password));
+
+ /* set the onu configuration */
+ BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, auto_password_learning, BCMOS_TRUE);
+ BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, us_fec, BCMOS_FALSE);
+
+ /* set the onu management channel port */
+ BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, omci_port_id, p_sub_term_req->data.svc_port_id);
+
+
+ rc = bcmolt_cfg_set(device_id, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to set onu configuration(%s), err_text=%s\n",
+ bcmos_strerror(rc), cfg.hdr.hdr.err_text);
+ break;
+ }
+
+ /**
+ * @note If this is first time set for ADD, then skip setting the ONU state for now.
+ * Wait until ONU Discovery is received.
+ */
+ break;
+ }
+
+
+ /* turn off the auto indication messages for gpon_onu.rei */
+ BCMOLT_AUTO_CFG_INIT(&gpon_onu_auto_cfg, gpon_onu, key);
+ BCMOLT_AUTO_CFG_PROP_SET(&gpon_onu_auto_cfg, gpon_onu, rei, BCMOS_FALSE);
+ rc = bcmolt_auto_cfg_set(device_id, &gpon_onu_auto_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "bcmolt_auto_cfg_set for gpon_onu.rei Failed (%s), err_text=%s)\n",
+ bcmos_strerror(rc), gpon_onu_auto_cfg.hdr.hdr.err_text);
+
+ /* This is not fatal, so just continue anyway */
+ }
+
+ /*
+ * Set the new onu state for the ADD operation
+ */
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Setting ONU state to active\n");
+
+ new_onu_state = BCMOLT_ONU_OPERATION_ACTIVE;
+ }
+ else if (BAL_UTIL_OPER_SUB_TERM_REMOVE == op_type)
+ {
+ /* If the ONU is not present, then it will never respond to the deactivate command
+ * with an indication, so just allow the FSM to continue as if it did.
+ */
+ if(BCMBAL_STATUS_NOT_PRESENT != p_sub_term_inst->current_sub_term_info.data.oper_status)
+ {
+ /*
+ * Set the new onu state for the REMOVE operation
+ */
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Setting ONU state to IN-active\n");
+
+ new_onu_state = BCMOLT_ONU_OPERATION_INACTIVE;
+ }
+ }
+ else /* This should never happen */
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Bad request from core\n");
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Do oper_submit to set the ONU state */
+ BCMOLT_OPER_PROP_SET(&oper, gpon_onu, set_onu_state, onu_state, new_onu_state);
+ rc = bcmolt_oper_submit(device_id, &oper.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "bcmolt_oper_submit Failed for onu state Failed (%s), err_text=%s\n",
+ bcmos_strerror(rc), &(oper.hdr.hdr.err_text[0]));
+ }
+
+
+ /* If the ONU is not present, then it will never respond to the deactivate command
+ * with an indication, so just allow the FSM to continue as if it did.
+ */
+ if((BCMOLT_ONU_OPERATION_INACTIVE == new_onu_state) &&
+ (BCMBAL_STATUS_NOT_PRESENT == p_sub_term_inst->current_sub_term_info.data.oper_status))
+ {
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_REMOVE,
+ rc, rc,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ }
+
+ } while (0);
+
+
+
+ if (rc == BCM_ERR_STATE)
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s failed to set state, possibly because interface is not configured yet, pon fiber disconnect, or onu disconnect: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+ else if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s Failed: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief validate_flow_info for gpon
+ *
+ * This routine is used to validate all input attributes required for a flow
+ * setting received from core for GPON
+ *
+ * @param p_flow_req A pointer to a flow object
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_validate_flow_info_for_gpon (const bcmbal_flow_cfg *p_flow_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ mac_util_topo_pon_context *topo_context;
+
+ topo_context = bcm_topo_pon_get_context(p_flow_req->data.access_int_id, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
+ if ((BCM_ERR_OK == rc) && (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode))
+ {
+ if (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, o_vid))
+ {
+ /* if the flow has an action to remove the outer tag from a double tagged OLT downstream packets,
+ the outer tag will be removed by the SWITCH in front of the MAC, the MAC should take the inner
+ tag vid for GEM decision. Sep-28-2015 IL
+ */
+ if (BCMOS_TRUE == mac_util_check_flow_is_double_tag_remove_o_tag (p_flow_req))
+ {
+ if (BCMOS_TRUE != BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, i_vid))
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "classifier i_vid id is a mandatory downstream parameter for double tagged action, "
+ "and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "o_vid id is a mandatory parameter for a flow classifier, and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+ }
+
+ if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, agg_port_id))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "agg port id is a mandatory parameter for an US flow, and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief flow set for GPON
+ *
+ * @param p_flow_req pointer to flow request structure from core
+ * @param op_type ADD, REMOVE or CLEAR
+ * @param p_flow_core local DB flow context passed as a cookie
+ *
+ * @return errno error
+ */
+bcmos_errno mac_util_flow_set_for_gpon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmos_bool is_pbit_enabled = BCMOS_FALSE;
+ uint16_t per_flow_mode_vlan_id = 0; /* hold the value of the vlan tag to use in per-flow mode */
+ uint8_t pbits_val = 0;
+ mac_util_topo_pon_context *topo_context;
+ flow_list_entry *p_mac_util_flow_entry = NULL;
+
+ topo_context = bcm_topo_pon_get_context(p_flow_req->data.access_int_id, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
+ if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
+ {
+ per_flow_mode_vlan_id = 0; /* set to default */
+
+ if (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, o_vid))
+ {
+ /* if the flow has an action to remove the outer tag from a double tagged OLT downstream packets,
+ the outer tag will be removed by the SWITCH in front of the MAC, the MAC should take the inner
+ tag vid for GEM decision. Sep-28-2015 IL
+ */
+ if (BCMOS_TRUE == mac_util_check_flow_is_double_tag_remove_o_tag (p_flow_req))
+ {
+ if (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, i_vid))
+ {
+ per_flow_mode_vlan_id = p_flow_req->data.classifier.i_vid;
+ }
+ //else should not happen here really, since this was validated in a previous step
+ }
+ else
+ {
+ per_flow_mode_vlan_id = p_flow_req->data.classifier.o_vid;
+ }
+ }
+ //else should not happen here really, since this was validated in a previous step
+ }
+
+
+ /* Check the operation id */
+ if ((BAL_UTIL_OPER_FLOW_ADD != op_type) &&
+ (BAL_UTIL_OPER_FLOW_REMOVE != op_type) &&
+ (BAL_UTIL_OPER_FLOW_CLEAR != op_type))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unexpected mac_util flow operation %d \n", op_type);
+ return BCM_ERR_PARM;
+ }
+
+ /* flow Add or Modify */
+ if (BAL_UTIL_OPER_FLOW_ADD == op_type)
+ {
+ switch (p_flow_req->key.flow_type)
+ {
+ /* unicast flows */
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ {
+ if (p_flow_req->data.classifier.o_pbits)
+ {
+ /* o_pbits can only take one p-bit value */
+ pbits_val = p_flow_req->data.classifier.o_pbits;
+ is_pbit_enabled = BCMOS_TRUE;
+ }
+ else
+ {
+ pbits_val = 0;
+ is_pbit_enabled = BCMOS_FALSE;
+ }
+
+ /* create a gem port id and relevant flow for a single pbit, or with no pbit */
+ /* pass on the op type also to specify if it is FLOW_ADD OR FLOW_MODIFY */
+ rc = maple_mac_unicast_flow_add(p_flow_req, pbits_val, per_flow_mode_vlan_id, op_type, &p_mac_util_flow_entry);
+ if ((BCM_ERR_OK != rc) || (NULL == p_mac_util_flow_entry))
+ {
+ break;
+ }
+
+
+ /* configure iwf flows in case of per flow interworking mode */
+ if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
+ {
+ if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type)
+ {
+ rc = maple_mac_ds_iwf_cfg(p_flow_req, per_flow_mode_vlan_id, is_pbit_enabled);
+ }
+ else
+ /* FLOW_TYPE_UPSTREAM */
+ {
+ rc = maple_mac_us_iwf_cfg(p_flow_req, pbits_val);
+ }
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Failed to add iwf flows in per flow mode (%s))\n",
+ bcmos_strerror(rc));
+ break;
+ }
+ }
+
+ /* mark flow configuration to device completed */
+ mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
+ }
+ break;
+
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ {
+ rc = maple_mac_broadcast_flow_add(p_flow_req, per_flow_mode_vlan_id, op_type, &p_mac_util_flow_entry);
+ if ((BCM_ERR_OK != rc) || (NULL == p_mac_util_flow_entry))
+ {
+ break;
+ }
+
+ }
+ break;
+
+ default:
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unknown flow type %d\n",
+ p_flow_req->key.flow_type);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else if ((BAL_UTIL_OPER_FLOW_REMOVE == op_type) ||
+ (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
+ {
+ /* find the flow */
+ p_mac_util_flow_entry = _mac_util_db_flow_get_w_flow_key(p_flow_req->data.access_int_id, &(p_flow_req->key));
+ if (NULL == p_mac_util_flow_entry)
+ {
+ rc = BCM_ERR_NOENT;
+ if (BAL_UTIL_OPER_FLOW_CLEAR != op_type)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "%s: NULL mac util flow entry to remove: flow id: %d, flow_type: %s\n",
+ __FUNCTION__,
+ p_flow_req->key.flow_id,
+ (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ? "up":"down"));
+ }
+
+ goto exit;
+ }
+
+ switch (p_flow_req->key.flow_type)
+ {
+ /* unicast flows */
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ {
+ /* First De-configure IWF flows in case of per flow interworking mode */
+ if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
+ {
+ if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type)
+ {
+ rc = maple_mac_ds_iwf_cfg_remove(p_flow_req, per_flow_mode_vlan_id);
+ }
+ else
+ {
+ rc = maple_mac_us_iwf_cfg_remove(p_flow_req);
+ }
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Failed to remove iwf flows in per flow mode (%s))\n",
+ bcmos_strerror(rc));
+ break;
+ }
+ }
+
+
+ /** Then remove unicast GEM/Alloc Id from Maple and flow entry from local database */
+ rc = maple_mac_unicast_flow_remove(p_flow_req, op_type, p_mac_util_flow_entry);
+ if (BCM_ERR_OK != rc)
+ {
+ break;
+ }
+
+ /* mark flow De-configuration to device completed */
+ mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
+ }
+ break;
+
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ {
+ rc = maple_mac_broadcast_flow_remove(p_flow_req, per_flow_mode_vlan_id, op_type, p_mac_util_flow_entry);
+ }
+ break;
+
+ default:
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unknown flow type %d\n",
+ p_flow_req->key.flow_type);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+
+ }
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unknown flow op type %d for flow id/type = %d/%d\n",
+ op_type, p_flow_req->key.flow_id, p_flow_req->key.flow_type);
+ rc = BCM_ERR_PARM;
+ }
+
+exit:
+ if (BCM_ERR_OK == rc)
+ {
+ /*
+ * Check flow entry flags to see if an indication to Core should be triggered immediately:
+ * (Special handling for flow configuration, for the case no device configuration is needed,
+ * and/or no indication from device is expected - could be the case of a single/multiple
+ * gem ports used for us and ds, and us was already configured.
+ * - send the flow ind immediately
+ */
+ check_send_flow_bal_ind_msg(p_mac_util_flow_entry, BCM_ERR_OK, BCMOLT_RESULT_SUCCESS);
+ }
+ else
+ {
+ if ((BCM_ERR_NOENT == rc) && (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
+ {
+ /*
+ * For flow CLEAR, and if no flow entry is found, then fake an indication success to Core,
+ * for it to execute the flow state machine.
+ * The reasons for flow entry not found could be because the flow was already admin-ed Down.
+ * Admin-down of a flow causes mac util to clear flow config and flow instance from itself
+ * and the maple HW. However, Core FSM still keeps it's flow instance during admin down state.
+ */
+ mac_util_report_flow_remove_success (p_flow_req->key, p_flow_req->data.access_int_id, op_type);
+ rc = BCM_ERR_OK;
+ }
+ }
+ //else if there was an error during config, just return a failure; no need to send back indication for that.
+
+
+ return rc;
+}
+
+bcmos_errno maple_gpon_mac_check_gem_port_id(uint32_t if_id, uint32_t onu_id, uint16_t svc_port_id,
+ bcmos_bool *is_configured, bcmos_bool *is_activated)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_gem_port_key gem_key = {};
+ bcmolt_gpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the gem port object key */
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, gpon_gem_port, gem_key);
+ BCMOLT_CFG_PROP_GET(&gem_cfg, gpon_gem_port, all_properties);
+
+ rc = bcmolt_cfg_get(device_id, &gem_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED in bcmolt_cfg_get: svc_port_id = %d if_id = %d onu_id = %d\n",
+ __FUNCTION__,
+ svc_port_id, if_id, onu_id);
+
+ return rc;
+ }
+
+
+ /* may be configured; does gem belong to same onu ? */
+ if (BCMOLT_GPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state && onu_id != gem_cfg.data.onu_id)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED, onu id mismatch: svc_port_id = %d if_id = %d is already assigned to onu_id = %d (not to onu id %d) \n",
+ __FUNCTION__,
+ svc_port_id, if_id, gem_cfg.data.onu_id, onu_id);
+
+ return BCM_ERR_PARM;
+ }
+ *is_configured = BCMOLT_GPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state;
+ *is_activated = BCMOLT_GPON_GEM_PORT_STATE_ACTIVE == gem_cfg.data.gem_port_state;
+
+ return rc;
+}
+
+
+bcmos_errno maple_gpon_gem_port_id_add(uint32_t if_id, uint16_t svc_port_id, uint32_t onu_id, bcmolt_gem_port_configuration *configuration)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_gem_port_key gem_key = {};
+ bcmolt_gpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the gem port object key */
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, gpon_gem_port, gem_key);
+
+ /* set the gem port configuration */
+ if (onu_id < MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM)
+ {
+ BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, onu_id, onu_id);
+ BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, upstream_destination_queue,
+ BCMOLT_US_GEM_PORT_DESTINATION_DATA);
+ }
+ BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, downstream_encryption_mode,
+ BCMOLT_CONTROL_STATE_DISABLE);
+ BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, configuration, *configuration);
+ BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, control, BCMOLT_CONTROL_STATE_ENABLE);
+
+ rc = bcmolt_cfg_set(device_id, &gem_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED: rc=%s (%d), svc_port_id = %d dev_id = %d if_id = %d onu_id = %d, err_text=%s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc, svc_port_id, device_id, if_id, onu_id, gem_cfg.hdr.hdr.err_text);
+ }
+
+ return rc;
+}
+
+
+bcmos_errno maple_gpon_gem_port_id_remove(uint32_t if_id, uint16_t svc_port_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_gem_port_key gem_key = {};
+ bcmolt_gpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, gpon_gem_port, gem_key);
+ rc = bcmolt_cfg_clear(device_id, &gem_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s id=%d, gem=%d, failed with error %s\n",__FUNCTION__, if_id, svc_port_id, bcmos_strerror(rc));
+ }
+
+
+ return rc;
+}
+
+
+bcmos_errno maple_gpon_mac_get_alloc_id_config (uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_alloc_state *alloc_id_state)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_alloc_key alloc_key = {};
+ bcmolt_gpon_alloc_cfg alloc_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the alloc-id key */
+ alloc_key.pon_ni = physical_if_id;
+ alloc_key.alloc_id = agg_id;
+ BCMOLT_CFG_INIT(&alloc_cfg, gpon_alloc, alloc_key);
+ BCMOLT_CFG_PROP_GET(&alloc_cfg, gpon_alloc, all_properties);
+
+ rc = bcmolt_cfg_get(device_id, &alloc_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s: FAILED in bcmolt_cfg_get rc = %s, agg_id = %d if_id = %d\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), agg_id, if_id);
+
+ return rc;
+ }
+
+ /* may be configured; does alloc id belong to the expected onu ? */
+ if (alloc_cfg.data.state != BCMOLT_ALLOC_STATE_NOT_CONFIGURED
+ && alloc_cfg.data.onu_id != onu_id)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED, onu id mismatch: agg_id = %d if_id = %d is set to onu %d NOT to onu_id = %d\n",
+ __FUNCTION__,
+ agg_id, if_id, alloc_cfg.data.onu_id, onu_id);
+
+ return BCM_ERR_PARM;
+ }
+
+ *alloc_id_state = alloc_cfg.data.state;
+
+ return BCM_ERR_OK;
+}
+
+
+bcmos_errno maple_gpon_us_alloc_id_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla agg_sla)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_alloc_key alloc_key = {};
+ bcmolt_gpon_alloc_cfg alloc_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the alloc-id key */
+ alloc_key.pon_ni = physical_if_id;
+ alloc_key.alloc_id = agg_id;
+ BCMOLT_CFG_INIT(&alloc_cfg, gpon_alloc, alloc_key);
+ BCMOLT_CFG_PROP_SET(&alloc_cfg, gpon_alloc, sla, agg_sla);
+ /* set the alloc-id - onu assignment */
+ BCMOLT_CFG_PROP_SET(&alloc_cfg, gpon_alloc, onu_id, onu_id);
+
+ rc = bcmolt_cfg_set(device_id, &alloc_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s: rc = %s, agg_id = %d if_id = %d, err_text = %s \n",
+ __FUNCTION__,
+ bcmos_strerror(rc), agg_id, if_id, alloc_cfg.hdr.hdr.err_text);
+ }
+ return rc;
+
+}
+
+
+bcmos_errno maple_gpon_us_alloc_id_remove(uint32_t if_id, uint16_t agg_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_gpon_alloc_key alloc_key = {};
+ bcmolt_gpon_alloc_cfg alloc_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the alloc-id key */
+ alloc_key.pon_ni = physical_if_id;
+ alloc_key.alloc_id = agg_id;
+ BCMOLT_CFG_INIT(&alloc_cfg, gpon_alloc, alloc_key);
+
+ rc = bcmolt_cfg_clear(device_id, &alloc_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ }
+
+ return rc;
+}
+
+/**
+ * @brief group set for gpon
+ * @param p_group_req pointer to group request structure from core
+ * @param op_type ADD, REMOVE or SET
+ * @param p_group_inst pointer to the Core Group Object instance
+ *
+ * @return errno error
+ *
+ * @todo shift this out to mac specific files
+ */
+bcmos_errno mac_util_group_set_for_gpon (bcmbal_group_cfg *p_group_req, bal_util_oper_group op_type, group_inst *p_group_inst)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint16_t svc_port_id;
+ uint32_t if_id, i, ref_count;
+ bcmolt_gem_port_configuration configuration = {0};
+
+ /* Check the operation id */
+ if ((BAL_UTIL_OPER_GROUP_ADD != op_type) &&
+ (BAL_UTIL_OPER_GROUP_REMOVE != op_type) &&
+ (BAL_UTIL_OPER_GROUP_SET != op_type))
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Unexpected mac_util gpon group operation %d \n", op_type);
+ return BCM_ERR_PARM;
+ }
+
+ configuration.direction = BCMOLT_GEM_PORT_DIRECTION_DOWNSTREAM;
+ configuration.type = BCMOLT_GEM_PORT_TYPE_MULTICAST;
+
+ /* for group SET operation, first remove the old multicast GEM */
+ if (BAL_UTIL_OPER_GROUP_SET == op_type)
+ {
+ bcmbal_group_cfg *p_group_rem_req;
+ /* use the Core DB for existing members - store in current_flow_info */
+ p_group_rem_req = &p_group_inst->current_group_info;
+ for(i=0; i< p_group_rem_req->data.members.len; i++)
+ {
+ if_id = p_group_rem_req->data.members.val[i].intf_id;
+ svc_port_id = p_group_rem_req->data.members.val[i].svc_port_id;
+ /* svc_port_id can be 0 (not assigned) when group had no owner, no need to remove */
+ if(svc_port_id)
+ {
+ rc = rsc_mgr_gem_get_ref_count(if_id, svc_port_id, &ref_count);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util gpon group get reference count on interface %d (gem %d) failed \n", if_id, svc_port_id);
+ return rc;
+ }
+ /* if other group is referencing the same GEM (ref_count > 1), do not call Mac API to remove it.
+ The core will ask Resource Manger to decrease the counter if everything is good */
+ if ( ref_count == 1)
+ {
+ rc = maple_gpon_gem_port_id_remove(if_id, svc_port_id);
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util gpon group set operation SET on remove interface %d (gem %d) failed \n", if_id, svc_port_id);
+ return rc;
+ }
+ }
+ else if ( ref_count == 0)
+ {
+ BCM_LOG(WARNING, log_id_mac_util,
+ "mac_util gpon group set operation SET on interface %d (gem %d) remove with 0 reference counter \n", if_id, svc_port_id);
+ }
+ }
+ }
+ }
+
+ /* walk through every member interface */
+ for(i=0; i< p_group_req->data.members.len; i++)
+ {
+ if_id = p_group_req->data.members.val[i].intf_id;
+ svc_port_id = p_group_req->data.members.val[i].svc_port_id;
+ /* group Add */
+ if (BAL_UTIL_OPER_GROUP_ADD == op_type || BAL_UTIL_OPER_GROUP_SET == op_type)
+ {
+ rc = maple_gpon_gem_port_id_add(if_id, svc_port_id, MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM, &configuration);
+ }
+ else if (BAL_UTIL_OPER_GROUP_REMOVE == op_type)
+ {
+ rc = rsc_mgr_gem_get_ref_count(if_id, svc_port_id, &ref_count);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util gpon group operation REM on interface %d (gem %d) failed \n", if_id, svc_port_id);
+ break;
+ }
+ /* if other group is referencing the same GEM (ref_count > 1), do not call Mac API to remove it.
+ The core will ask Resource Manger to decrease the counter if everything is good */
+ if ( ref_count == 1)
+ {
+ rc = maple_gpon_gem_port_id_remove(if_id, svc_port_id);
+ }
+ else if ( ref_count == 0)
+ {
+ BCM_LOG(WARNING, log_id_mac_util,
+ "mac_util gpon group operation REM on interface %d (gem %d) with 0 reference count \n", if_id, svc_port_id);
+ }
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util gpon group set of operation %d on interface %d (gem %d) failed \n", op_type, if_id, svc_port_id);
+ break;
+ }
+ }
+
+
+ return rc;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util_loopback.c b/bal_release/src/core/util/mac/bal_mac_util_loopback.c
new file mode 100644
index 0000000..e94c282
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_loopback.c
@@ -0,0 +1,149 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_loopback.c
+ *
+ * @brief mac util handling for MAC in loopback mode
+ *
+ * The loopback mode is handled like a mac protocol, with loopback specific handling
+ * done as sub-routine calls from the top level handler functions.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+#include <bal_mac_util_common_itu_pon.h>
+#include <bal_worker.h>
+
+
+/**
+ * @brief access terminal set for loopback
+ */
+bcmos_errno mac_util_access_terminal_set_for_loopback (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmos_usleep(1000000);
+ mac_util_report_acc_term_event(BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE);
+
+ return rc;
+}
+
+
+/**
+ * @brief set interface for loopback mode
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param op_type Operation type on access terminal/interface instance
+ *
+ * @return bcmos_errno
+ *
+ */
+bcmos_errno mac_util_interface_set_for_loopback(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key;
+ bcmbal_interface_cfg *p_interface_req = &(p_interface_inst->api_req_int_obj_info);
+
+ p_interface_req = &(p_interface_inst->api_req_int_obj_info);
+
+ /* If the user didn't specify a transceiver, then use the default */
+ if (BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_interface_req, interface, transceiver_type))
+ {
+ BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_GPON);
+ }
+
+ mac_util_report_if_event(intf_key.intf_id,
+ intf_key.intf_type,
+ BCM_ERR_OK, BCMOLT_RESULT_SUCCESS,
+ ((BAL_UTIL_OPER_IF_UP == op_type) ? BCMOLT_PON_STATE_ACTIVE_WORKING : BCMOLT_PON_STATE_INACTIVE));
+
+
+ return rc;
+}
+
+
+/**
+ * @brief Set subscriber terminal for loopback mode
+ *
+ * @param p_sub_term_inst A pointer to a subscriber terminal instance
+ * @param op_type Type of operation being performed on the subscriber terminal instance
+ * @param is_post_discovery Used for ADD, indicates if this request is after a ONU Discovery
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_subscriber_terminal_set_for_loopback(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
+
+
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ (BAL_UTIL_OPER_SUB_TERM_ADD == op_type ? BAL_UTIL_OPER_SUB_TERM_ADD : BAL_UTIL_OPER_SUB_TERM_REMOVE),
+ BCM_ERR_OK, BCMOLT_RESULT_SUCCESS,
+ (BAL_UTIL_OPER_SUB_TERM_ADD == op_type ? BCMOLT_ACTIVATION_FAIL_REASON_NONE : BCMOLT_RESULT_SUCCESS), BCMBAL_INVALID_TUNNEL_ID);
+
+ return rc;
+}
+
+
+/**
+ * @brief set flow for loopback mode
+ */
+bcmos_errno mac_util_flow_set_for_loopback(bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (BAL_UTIL_OPER_FLOW_ADD == op_type)
+ {
+ mac_util_report_flow_add_success(p_flow_req->key, p_flow_req->data.access_int_id);
+ }
+ else if ((BAL_UTIL_OPER_FLOW_REMOVE == op_type) || (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
+ {
+ mac_util_report_flow_remove_success(p_flow_req->key, p_flow_req->data.access_int_id, op_type);
+ }
+ else
+ {
+ rc = BCM_ERR_INVALID_OP;
+ }
+
+
+ return rc;
+}
+
+
+
+/*@}*/
diff --git a/bal_release/src/core/util/mac/bal_mac_util_xgpon.c b/bal_release/src/core/util/mac/bal_mac_util_xgpon.c
new file mode 100644
index 0000000..a49b3d7
--- /dev/null
+++ b/bal_release/src/core/util/mac/bal_mac_util_xgpon.c
@@ -0,0 +1,1493 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_mac_util_xgpon.c
+ *
+ * @brief mac util interfaces definition used by Bal Core, for xgpon
+ *
+ * This file expose the APIs to the core to configure the mac
+ * with regarding to the operation of access terminal, interface, subscriber terminal and flow.
+ *
+ * @addtogroup mac_util
+ */
+
+/*@{*/
+
+#include <bal_mac_util.h>
+#include <bal_mac_util_common_itu_pon.h>
+
+
+static bcmos_errno mac_util_indication_handle_for_xgpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_indication_handle_for_xgpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg);
+static bcmos_errno mac_util_indication_handle_for_xgpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg);
+
+/* On XG-PON1 there is no indication such as GEM port configuration completed.
+ * GEM configuration at the ONU is taken care of completely by OMCI without any PLOAM sent from the OLT
+ * */
+
+/**
+ * @brief array stores the list of xgpon (XG-PON1) related auto indications from Maple to subscribe
+ */
+static mac_util_ind_obj_and_handlers mac_util_xgpon_ind_handlers[] =
+{
+ {BCMOLT_OBJ_ID_XGPON_NI, "BCMOLT_OBJ_ID_XGPON_NI", mac_util_indication_handle_for_xgpon_ni},
+ {BCMOLT_OBJ_ID_XGPON_ONU, "BCMOLT_OBJ_ID_XGPON_ONU", mac_util_indication_handle_for_xgpon_onu},
+ {BCMOLT_OBJ_ID_XGPON_ALLOC, "BCMOLT_OBJ_ID_XGPON_ALLOC", mac_util_indication_handle_for_xgpon_alloc_id},
+};
+
+/**
+ * @brief Map bal XGPON transceiver type to bcm68620 transceiver type
+ */
+static bcmolt_xgpon_trx_type mac_xgpon_bal_trx_type2bcm68620_trx_type(bcmbal_trx_type bal_trx_type)
+{
+ bcmolt_xgpon_trx_type trx_type = BCMOLT_XGPON_TRX_TYPE__NUM_OF;
+
+ if (BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC == bal_trx_type)
+ {
+ trx_type = BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC;
+ }
+ else if (BCMBAL_TRX_TYPE_XGPON_LTH_7226_PC == bal_trx_type)
+ {
+ trx_type = BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC;
+ }
+ else if (BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC == bal_trx_type)
+ {
+ trx_type = BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC;
+ }
+ else
+ {
+ trx_type = BCMOLT_XGPON_TRX_TYPE_USER_DEFINED;
+ }
+
+ return trx_type;
+}
+
+/**
+ * @brief all the maple indication handlers for xgpon
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ */
+bcmos_errno mac_util_handle_all_olt_ind_for_xgpon (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ BCM_LOG(DEBUG, log_id_mac_util,
+ "mac_util_indication_cb received indication obj=%d/%s group=%d subgroup=%d\n",
+ p_msg->obj_type, mac_util_indication_get_obj_type_str(p_msg->obj_type, mac_util_xgpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_xgpon_ind_handlers)),
+ p_msg->group, p_msg->subgroup);
+
+ return mac_util_handle_indication(device_id, p_msg, mac_util_xgpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_xgpon_ind_handlers));
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for xgpon (XG-PON1) NI
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_xgpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+
+ do
+ {
+
+ /* PON activation */
+ if (BCMOLT_XGPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_xgpon_ni_state_change_completed * p_ind = (bcmolt_xgpon_ni_state_change_completed*)p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), "Pon if %d is %s.\n", logical_pon,
+ BCMOLT_PON_STATE_ACTIVE_WORKING == p_ind->data.new_state ? "up" : "down");
+
+ mac_util_report_if_event(logical_pon, BCMBAL_INTF_TYPE_PON, p_msg->err,
+ p_ind->data.result, p_ind->data.new_state);
+
+ }
+ else if(BCMOLT_XGPON_NI_AUTO_CFG_ID_ONU_DISCOVERED == p_msg->subgroup)
+ {
+ bcmolt_xgpon_ni_onu_discovered *p_ind =
+ (bcmolt_xgpon_ni_onu_discovered *)p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Pon if %d found ONU serial number "
+ "%c%c%c%c%d%d%d%d%d%d%d%d\n",
+ logical_pon,
+ p_ind->data.serial_number.vendor_id[0],
+ p_ind->data.serial_number.vendor_id[1],
+ p_ind->data.serial_number.vendor_id[2],
+ p_ind->data.serial_number.vendor_id[3],
+ p_ind->data.serial_number.vendor_specific[0]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[0] & 0x0f,
+ p_ind->data.serial_number.vendor_specific[1]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[1] & 0x0f,
+ p_ind->data.serial_number.vendor_specific[2]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[2] & 0x0f,
+ p_ind->data.serial_number.vendor_specific[3]>>4 & 0x0f,
+ p_ind->data.serial_number.vendor_specific[3] & 0x0f
+ );
+
+ /* if we got something from MAC HW, then it has to be PON interface */
+ mac_util_report_sub_term_event(logical_pon,
+ p_ind->data.onu_id,
+ &p_ind->data.serial_number,
+ BAL_UTIL_OPER_SUB_TERM_DISCOVERY,
+ p_msg->err, BCM_ERR_OK,
+ BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ }
+
+ else
+ {
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_xgpon_ni_key *p_pon_key = &(((bcmolt_xgpon_ni_state_change_completed*)p_msg)->key);
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj XGPON_NI group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ }
+ }
+ while(0);
+
+ return rc;
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for xgpon (XG-PON1) ONU
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_xgpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_xgpon_onu_key *p_xgpon_onu_key = &(((bcmolt_xgpon_onu_onu_activation_completed*)p_msg)->key);
+ do
+ {
+ if (BCMOLT_XGPON_ONU_AUTO_CFG_ID_ONU_ACTIVATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_xgpon_onu_onu_activation_completed *p_ind = (bcmolt_xgpon_onu_onu_activation_completed*) p_msg;
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "sub_term %d (PON%d) activation indication (%s)\n",
+ p_ind->key.onu_id,
+ logical_pon,
+ bcmos_strerror(p_msg->err));
+
+ mac_util_report_sub_term_event(logical_pon,
+ p_ind->key.onu_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_ADD,
+ p_msg->err, p_ind->data.status,
+ p_ind->data.fail_reason, BCMBAL_INVALID_TUNNEL_ID);
+
+ }
+ else if(BCMOLT_XGPON_ONU_AUTO_CFG_ID_ONU_DEACTIVATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_xgpon_onu_onu_deactivation_completed *p_ind = (bcmolt_xgpon_onu_onu_deactivation_completed*) p_msg;
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "sub_term %d (PON%d) deactivation indication (%s)\n",
+ p_ind->key.onu_id,
+ p_ind->key.pon_ni,
+ bcmos_strerror(p_msg->err));
+
+ mac_util_report_sub_term_event(logical_pon,
+ p_ind->key.onu_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_REMOVE,
+ p_msg->err, p_ind->data.status,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ }
+ else
+ {
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_xgpon_onu_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_xgpon_onu_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj XGPON_ONU group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ break;
+ }
+
+ rc = mac_util_update_flows_w_sub_term_update(logical_pon, p_xgpon_onu_key->onu_id, maple_xgpon_mac_check_gem_port_id, maple_xgpon_mac_get_alloc_id_config);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to update related flows pon_id = %d onu_id = %d (%s)\n", logical_pon, p_xgpon_onu_key->onu_id, bcmos_strerror(rc));
+ break;
+ }
+
+ }while(0);
+
+ return rc;
+}
+
+
+/**
+ * @brief Handler function for Maple auto indications for xgpon (XG-PON1) Alloc Id
+ *
+ * @param device_id the maple device id generating the current indication
+ * @param p_msg pointer to the maple indication message
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno mac_util_indication_handle_for_xgpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t logical_pon;
+ tm_sched_inst* p_tm_sched_inst = NULL;
+ do
+ {
+ if (BCMOLT_XGPON_ALLOC_AUTO_CFG_ID_CONFIGURATION_COMPLETED == p_msg->subgroup)
+ {
+ bcmolt_xgpon_alloc_configuration_completed *p_ind = (bcmolt_xgpon_alloc_configuration_completed*) p_msg;
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
+
+ break;
+ }
+
+ /* Find tn_mode inst owned by that alloc_id and ni */
+ p_tm_sched_inst = tm_sched_find_agg_port_node(logical_pon, p_ind->key.alloc_id);
+ if (NULL == p_tm_sched_inst )
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to find tm sched owned by that agg port (intf %d id %d)\n", logical_pon,p_ind->key.alloc_id);
+ rc = BCM_ERR_NOENT;
+ break;
+
+ }
+
+ /*the tm owned by that alloc found, update it with the ind*/
+ mac_util_report_tm_sched_set_indication(p_tm_sched_inst->req_tm_sched_info.key ,p_msg->err, p_ind->data.status);
+
+ }
+ else
+ {
+ /* just get the pon key by typecasting to a dummy structure */
+ bcmolt_xgpon_alloc_key *p_pon_key = &(((bcmolt_xgpon_alloc_configuration_completed*)p_msg)->key);
+
+ rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
+ break;
+ }
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Unhandled message indication for obj XGPON_ALLOC group %d "
+ "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
+ }
+
+ }
+ while (0);
+ return rc;
+}
+
+
+/**
+ * @brief Maple auto indication register for specific xgpon (XG-PON1) based indications
+ *
+ * @param p_rx_cfg handler config structure
+ * @param device_id specific device id (for multiple devices support)
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_register_for_xgpon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id)
+{
+ return _mac_util_register_for_auto_indications (p_rx_cfg, mac_util_xgpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_xgpon_ind_handlers),device_id);
+}
+
+
+/**
+ * @brief common access terminal set for 10G pon if
+ */
+
+bcmos_errno mac_util_access_terminal_set_for_10G_itu_pon (bcmolt_device_cfg dev_cfg, bcmolt_devid device_id)
+{
+ bcmos_errno rc;
+ bcmolt_device_nni_speed nni_speed_cfg;
+
+#ifdef QAX_SWITCH
+ /* until speed is configurable through topology settings hardcode it based on switch type */
+ BCM_LOG(INFO, log_id_mac_util, "nni speed is: 10G\n");
+ nni_speed_cfg.first_half = BCMOLT_NNI_SPEED_GBPS_10;
+ nni_speed_cfg.second_half = BCMOLT_NNI_SPEED_GBPS_10;
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, nni_speed, nni_speed_cfg);
+#endif
+
+ rc = bcmolt_cfg_set(device_id, &dev_cfg.hdr);
+
+ return rc;
+}
+
+
+/**
+ * @brief access terminal set for xgpon1_8
+ */
+bcmos_errno mac_util_access_terminal_set_for_xgpon_8 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
+{
+ bcmos_errno rc;
+ bcmolt_device_key key = {};
+ bcmolt_device_cfg dev_cfg;
+
+ rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ BCMOLT_CFG_INIT(&dev_cfg, device, key);
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, BCMOLT_SYSTEM_MODE_XGPON_1__8_X);
+
+ rc = mac_util_access_terminal_set_for_10G_itu_pon(dev_cfg,device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ return maple_access_terminal_connect_common(device_id);
+}
+
+
+/**
+ * @brief access terminal set for xgs_2_10
+ */
+bcmos_errno mac_util_access_terminal_set_for_xgs (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
+{
+ bcmos_errno rc;
+ bcmolt_device_key key = {};
+ bcmolt_device_cfg dev_cfg;
+
+ rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ BCMOLT_CFG_INIT(&dev_cfg, device, key);
+ BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X_10_G);
+
+ rc = mac_util_access_terminal_set_for_10G_itu_pon(dev_cfg, device_id);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ return maple_access_terminal_connect_common(device_id);
+}
+
+
+/**
+ * @brief post access terminal up configurations on Maple
+ */
+bcmos_errno mac_util_access_terminal_post_indication_set_for_xgpon_xgs(bcmolt_devid device_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_devid dummy;
+ uint32_t physical_if_id;
+ uint32_t logical_pon = BCM_TOPO_PON_INVALID;
+ bcmolt_xgpon_ni_key ni_key = {};
+ bcmolt_xgpon_ni_cfg ni_cfg = {};
+ bcmolt_automatic_onu_deactivation automatic_onu_deactivation = {};
+ bcmolt_xgpon_sn_acquisition sn_acquisition_cfg = {};
+ bcmolt_xgpon_ni_auto_cfg xgpon_ni_auto_cfg = {}; /* main auto cfg api struct */
+
+ /* configure one time settings for all the interfaces on this device */
+ BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon)
+ {
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (logical_pon, &dummy, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ ni_key.pon_ni = physical_if_id;
+
+ /* Set the SN acquisition mode to enable */
+ BCMOLT_CFG_INIT(&ni_cfg, xgpon_ni, ni_key);
+
+ sn_acquisition_cfg.control = BCMOLT_CONTROL_STATE_ENABLE;
+ sn_acquisition_cfg.interval = 5000;
+ sn_acquisition_cfg.onu_post_discovery_mode = BCMOLT_ONU_POST_DISCOVERY_MODE_NONE;
+ sn_acquisition_cfg.burst_profile = 0; /* Ranging burst profile - No FEC */
+ BCMOLT_CFG_PROP_SET(&ni_cfg, xgpon_ni, sn_acquisition, sn_acquisition_cfg);
+
+ /* Unlike GPON, the default behavior on Maple for XG-PON1 is not to deactivate the ONU in the below cases
+ * so here we specifically configure the Maple to behave on XG-PON1 as it does on GPON */
+ automatic_onu_deactivation.ack_timeout = BCMOS_TRUE;
+ automatic_onu_deactivation.loki = BCMOS_TRUE;
+ automatic_onu_deactivation.los = BCMOS_TRUE;
+ automatic_onu_deactivation.onu_alarms = BCMOS_TRUE;
+ automatic_onu_deactivation.sfi = BCMOS_TRUE;
+ automatic_onu_deactivation.tiwi = BCMOS_TRUE;
+ BCMOLT_CFG_PROP_SET(&ni_cfg, xgpon_ni, automatic_onu_deactivation, automatic_onu_deactivation);
+
+ rc = bcmolt_cfg_set(device_id, &ni_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "Failed to set sn acquisition and automatic onu deactivation configuration (%s),"
+ " device_id=%d, ni_key.pon_ni=%d, err_text=%s)\n",
+ bcmos_strerror(rc), device_id, ni_key.pon_ni, ni_cfg.hdr.hdr.err_text);
+ break;
+ }
+
+
+ /* turn off the auto indication messages for xgpon_ni.serial_number_acquisition_cycle_start */
+ BCMOLT_AUTO_CFG_INIT(&xgpon_ni_auto_cfg, xgpon_ni, ni_key);
+ BCMOLT_AUTO_CFG_PROP_SET(&xgpon_ni_auto_cfg, xgpon_ni, serial_number_acquisition_cycle_start, BCMOS_FALSE);
+ rc = bcmolt_auto_cfg_set(device_id, &xgpon_ni_auto_cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
+ "bcmolt_auto_cfg_set for xgpon_ni.serial_number_acquisition_cycle_start, Failed (%s), err_text=%s)\n",
+ bcmos_strerror(rc), xgpon_ni_auto_cfg.hdr.hdr.err_text);
+
+ /* ignore any error, just continue anyway */
+ }
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief Command Set setup routine for interface up to mac application for xgpon (XG-PON1)
+ *
+ * This routine is called by if_fsm in the BAL core to initialize the command
+ * set to up the interface of the mac application. The cmdset actually
+ * consists of two commands, one is to send the if up request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param op_type Operation type on access terminal/interface instance
+ *
+ * @return bcmos_errno
+ *
+ */
+bcmos_errno mac_util_interface_set_for_xgpon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmbal_interface_cfg *p_interface_req = &(p_interface_inst->api_req_int_obj_info);
+ bcmbal_interface_key intf_key = p_interface_req->key;
+
+ do
+ {
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (intf_key.intf_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ bcmolt_xgpon_ni_set_pon_state oper_ni;
+ bcmolt_xgpon_ni_key ni_key = { .pon_ni = physical_if_id };
+ bcmolt_xgpon_trx_cfg cfg = {};
+ bcmolt_xgpon_trx_key trx_key = { .pon_ni = physical_if_id };
+ bcmolt_xgpon_trx_type trx_type;
+
+ if (BAL_UTIL_OPER_IF_UP == op_type)
+ {
+
+ /* set the pon_ni transceiver configuration */
+ BCMOLT_CFG_INIT(&cfg, xgpon_trx, trx_key);
+
+ /* Get the current default burst profiles */
+ rc = bcmolt_cfg_get(device_id, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to get trx configuration (%s), err_text=%s\n", bcmos_strerror(rc), cfg.hdr.hdr.err_text);
+ break;
+ }
+
+ /* If the user didn't specify a transceiver, then use the default */
+ if (BCMOS_TRUE != BCMBAL_CFG_PROP_IS_SET(p_interface_req, interface, transceiver_type))
+ {
+ if(BCM_TOPO_PON_MODE_XGPON == bcm_topo_pon_get_pon_mode(intf_key.intf_id))
+ {
+ /* The user didn't choose a transceiver type, so override it here
+ * with the default value for XGPON
+ */
+ BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_XGPON);
+ }
+ else if (BCM_TOPO_PON_MODE_XGS == bcm_topo_pon_get_pon_mode(intf_key.intf_id))
+ {
+ /* The user didn't choose a transceiver type, so override it here
+ * with the default value for XGS
+ */
+ BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_XGS);
+ }
+ }
+
+ /* Set the (default or chosen) transceiver configuration into the MAC device */
+
+ trx_type = mac_xgpon_bal_trx_type2bcm68620_trx_type(p_interface_req->data.transceiver_type);
+
+ BCMOLT_CFG_PROP_SET(&cfg, xgpon_trx, transceiver_type, trx_type);
+
+ rc = bcmolt_cfg_set(device_id, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to set trx configuration (%s), err_text=%s\n", bcmos_strerror(rc), cfg.hdr.hdr.err_text);
+ break;
+ }
+
+ /* No need to Configure pon_ni Inter-working on XG-PON1 as
+ * direct mode is the only option available on this system mode
+ */
+ }
+
+
+ /* invoke the pon_ni state change to the requested state */
+ BCMOLT_OPER_INIT(&oper_ni, xgpon_ni, set_pon_state, ni_key);
+ BCMOLT_OPER_PROP_SET(&oper_ni, xgpon_ni, set_pon_state, pon_state,
+ (BAL_UTIL_OPER_IF_UP == op_type) ?
+ BCMOLT_PON_OPERATION_ACTIVE_WORKING : BCMOLT_PON_OPERATION_INACTIVE);
+
+ rc = bcmolt_oper_submit(device_id, &oper_ni.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Failed to %s (submit) pon interface (%s), err_text=%s\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
+ bcmos_strerror(rc), oper_ni.hdr.hdr.err_text);
+ }
+
+ } while (0);
+
+ if (BCM_ERR_OK == rc)
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
+ "Submitted INTERFACE-%s operation for IF %d\n",
+ (BAL_UTIL_OPER_IF_UP == op_type) ? "UP" : "DOWN",
+ intf_key.intf_id);
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief mac_util_validate_subscriber_terminal_info_for_xgpon (XG-PON1)
+ *
+ * This routine is used to validate all input attributes required for a sub term setting
+ * received from core for GPON
+ *
+ * @param p_sub_term_req A pointer to a subscriber terminal object
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_validate_subscriber_terminal_info_for_xgpon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req)
+{
+ if(BCMBAL_STATE_UP == p_sub_term_req->data.admin_state)
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET (p_sub_term_req, subscriber_terminal, serial_number))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Serial number is a mandatory parameter for a xgpon subscriber terminal, and it is not set\n");
+ return BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+
+ if (!BCMBAL_CFG_PROP_IS_SET(p_sub_term_req, subscriber_terminal, registration_id))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Registration id is a mandatory parameter for a xgpon subscriber terminal, and it is not set\n");
+ return BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief Command Set setup routine for subscriber terminal connect to mac application for xgpon (XG-PON1)
+ *
+ * This routine is called by sub_term_fsm in the BAL core to initialize the command
+ * set to connect the subscriber terminal of the mac application. The cmdset actually
+ * consists of two commands, one is to send the sub_term request message to the mac
+ * App and handle the relevant response, the other is to handle the indication message
+ * from the mac APP when the operation is completed.
+ *
+ * @param p_sub_term_inst A pointer to a subscriber terminal instance
+ * @param op_type Type of operation being performed on the subscriber terminal instance
+ * @param is_post_discovery Used for ADD, indicates if this is a request after a ONU discovery
+ *
+ * @return bcmos_errno
+ *
+ * @note we configure Maple for ONU in 2 stages:
+ * \li Stage 1: do cfg_set with the serial num, password, omci port, as part of first sub_term_set from Core
+ * \li Stage 2: set the ONU state to ACTIVE using oper_submit, as part of second sub_term_set from Core (after
+ * receiving a Discovery indication)
+ */
+bcmos_errno mac_util_subscriber_terminal_set_for_xgpon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
+
+ do
+ {
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+ /* get physical interface from logical interface */
+ rc = bcm_topo_pon_get_logical2physical (p_sub_term_req->key.intf_id, &device_id, &physical_if_id);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
+ break;
+ }
+
+ bcmolt_xgpon_onu_cfg cfg = {};
+ bcmolt_xgpon_onu_cfg onu_cfg_get = {};
+ bcmolt_xgpon_onu_set_onu_state oper = {};
+ bcmolt_xgpon_onu_key key = {};
+ bcmolt_onu_operation new_onu_state;
+
+ /* set the onu key - set it to the physical if id */
+ key.pon_ni = physical_if_id;
+ key.onu_id = p_sub_term_req->key.sub_term_id;
+
+ /* set the onu key */
+ BCMOLT_CFG_INIT(&cfg, xgpon_onu, key);
+
+ /* invoke onu state change operation to the new state */
+ BCMOLT_OPER_INIT(&oper, xgpon_onu, set_onu_state, key);
+
+ if(BAL_UTIL_OPER_SUB_TERM_CLEAR == op_type)
+ {
+ /* Delete the configuration of the ONU */
+ rc = bcmolt_cfg_clear(device_id, &cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to clear onu configuration(%s)\n",
+ bcmos_strerror(rc));
+ }
+
+ /* No indication from Maple will result from the clear operation
+ * so fake it here
+ */
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_CLEAR,
+ rc, rc,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+
+ /* No further processing is required for the CLEAR operation */
+ break;
+
+
+ }
+ else if(BAL_UTIL_OPER_SUB_TERM_ADD == op_type)
+ {
+ /* first do a get, to see if onu is in active state already */
+ BCMOLT_CFG_INIT(&onu_cfg_get, xgpon_onu, key);
+ BCMOLT_CFG_PROP_GET(&onu_cfg_get, xgpon_onu, onu_state);
+ rc = bcmolt_cfg_get(device_id, &onu_cfg_get.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to get onu configuration(%s), err_text=%s, ... continue to configure\n",
+ bcmos_strerror(rc), onu_cfg_get.hdr.hdr.err_text);
+
+ /* don't break, but continue with the set anyways */
+ }
+ else
+ {
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s: ONU state = %d, [pon_ni=%d, onu_id=%d], BEFORE doing cfg_set on Maple\n",
+ __FUNCTION__, onu_cfg_get.data.onu_state, onu_cfg_get.key.pon_ni, onu_cfg_get.key.onu_id);
+ }
+
+
+ if ((BCM_ERR_OK == rc) && (BCMOLT_ONU_STATE_ACTIVE == onu_cfg_get.data.onu_state))
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s: ONU already in active state during ADD. Skipping further config\n",
+ __FUNCTION__);
+
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_ADD,
+ rc, rc,
+ BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ break;
+ }
+
+
+ /* set the SN & Registration ID only if it being configured for the first time */
+ if (BCMOS_FALSE == is_post_discovery)
+ {
+ BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, serial_number,
+ *((bcmolt_serial_number *)&p_sub_term_req->data.serial_number));
+
+ BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, registration_id,
+ *((bcmolt_arr_u8_36 *)&p_sub_term_req->data.registration_id));
+
+ BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, registration_id_auto_learning, BCMOS_TRUE);
+
+ /* Ranging burst profile - No FEC */
+ BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, ranging_burst_profile, 0);
+
+ /* Data burst profile - No FEC */
+ BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, data_burst_profile, 1);
+
+
+ /* XG-PON1 - No need to set US FEC - it is part of the burst profile */
+ /* XG-PON1 - No need to set ONU management channel port as it is identical to the ONU ID*/
+
+ rc = bcmolt_cfg_set(device_id, &cfg.hdr);
+ if (rc != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Failed to set onu configuration(%s), err_text=%s\n",
+ bcmos_strerror(rc), cfg.hdr.hdr.err_text);
+ break;
+ }
+
+ /**
+ * @note If this is first time set for ADD, then skip setting the ONU state for now.
+ * Wait until ONU Discovery is received.
+ */
+ break;
+ }
+
+ /*
+ * Set the new onu state for the ADD operation
+ */
+ BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Setting ONU state to active\n");
+
+ new_onu_state = BCMOLT_ONU_OPERATION_ACTIVE;
+ }
+ else if (BAL_UTIL_OPER_SUB_TERM_REMOVE == op_type)
+ {
+ /* If the ONU is not present, then it will never respond to the deactivate command
+ * with an indication, so just allow the FSM to continue as if it did.
+ */
+ if(BCMBAL_STATUS_NOT_PRESENT != p_sub_term_inst->current_sub_term_info.data.oper_status)
+ {
+ /*
+ * Set the new onu state for the REMOVE operation
+ */
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "Setting ONU state to IN-active\n");
+
+ new_onu_state = BCMOLT_ONU_OPERATION_INACTIVE;
+ }
+ }
+ else /* This should never happen */
+ {
+ BCM_LOG(ERROR, log_id_mac_util, "Bad request from core\n");
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Do oper_submit to set the ONU state */
+ BCMOLT_OPER_PROP_SET(&oper, xgpon_onu, set_onu_state, onu_state, new_onu_state);
+ rc = bcmolt_oper_submit(device_id, &oper.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "bcmolt_oper_submit Failed for onu state Failed (%s), err_text=%s\n",
+ bcmos_strerror(rc), &(oper.hdr.hdr.err_text[0]));
+ }
+
+
+ /* If the ONU is not present, then it will never respond to the deactivate command
+ * with an indication, so just allow the FSM to continue as if it did.
+ */
+ if((BCMOLT_ONU_OPERATION_INACTIVE == new_onu_state) &&
+ (BCMBAL_STATUS_NOT_PRESENT == p_sub_term_inst->current_sub_term_info.data.oper_status))
+ {
+ mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
+ p_sub_term_req->key.sub_term_id,
+ (bcmolt_serial_number *)NULL,
+ BAL_UTIL_OPER_SUB_TERM_REMOVE,
+ rc, rc,
+ MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
+ }
+
+ } while (0);
+
+
+
+ if (rc == BCM_ERR_STATE)
+ {
+ BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s failed to set state, possibly because interface is not configured yet, pon fiber disconnect, or onu disconnect: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+ else if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
+ "%s Failed: rc = %s (%d)\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc);
+ }
+
+ return rc;
+}
+
+
+/**
+ * @brief validate_flow_info for xgpon (XG-PON1)
+ *
+ * This routine is used to validate all input attributes required for a flow
+ * setting received from core for XG-PON1
+ *
+ * @param p_flow_req A pointer to a flow object
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno mac_util_validate_flow_info_for_xgpon (const bcmbal_flow_cfg *p_flow_req)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ {
+ if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, agg_port_id))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "agg port id is a mandatory parameter for an US flow, and it is not set\n");
+ rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
+ }
+
+ }
+
+ return rc;
+}
+/* As there is no indication on gem port configuration completion, for xgpon
+ we will have to initiate querying it right after configuring it and retrieve the gem port state.
+ we can not assume it is activated (for example if the onu is not present)
+*/
+static bcmos_errno maple_mac_xgpon_update_svc_port_ind_flag (bcmbal_flow_cfg *p_flow_req, flow_list_entry *p_mac_util_flow_entry)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_gem_port_key gem_key = {};
+ bcmolt_xgpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(p_flow_req->data.access_int_id, device_id, physical_if_id);
+
+ /* set the gem port object key */
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = p_flow_req->data.svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, xgpon_gem_port, gem_key);
+ BCMOLT_CFG_PROP_GET(&gem_cfg, xgpon_gem_port, all_properties);
+
+ rc = bcmolt_cfg_get(device_id, &gem_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "%s FAILED to gem xgpon_gem_port configuration : device_id = %d if_id = %d gem_port_id = %d \n",
+ __FUNCTION__,
+ device_id, p_flow_req->data.access_int_id, p_flow_req->data.svc_port_id);
+
+ return rc;
+ }
+
+ if ( BCMOLT_XGPON_GEM_PORT_STATE_ACTIVE == gem_cfg.data.gem_port_state)
+ {
+ p_mac_util_flow_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
+ }
+ return rc;
+}
+
+/**
+ * @brief flow set for xgpon (XG-PON1)
+ * @param p_flow_req pointer to flow request structure from core
+ * @param op_type ADD, REMOVE or CLEAR
+ * @param p_flow_core core FSM DB flow context passed as a cookie
+ *
+ * @return errno error
+ *
+ * @todo shift this out to mac specific files
+ */
+bcmos_errno mac_util_flow_set_for_xgpon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint16_t per_flow_mode_vlan_id = 0; /* hold the value of the vlan tag to use in per-flow mode */
+ uint8_t pbits_val = 0;
+ flow_list_entry *p_mac_util_flow_entry = NULL;
+
+ /* Check the operation id */
+ if ((BAL_UTIL_OPER_FLOW_ADD != op_type) &&
+ (BAL_UTIL_OPER_FLOW_REMOVE != op_type) &&
+ (BAL_UTIL_OPER_FLOW_CLEAR != op_type))
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unexpected mac_util flow operation %d \n", op_type);
+ return BCM_ERR_PARM;
+ }
+
+ /* flow Add or Modify */
+ if (BAL_UTIL_OPER_FLOW_ADD == op_type)
+ {
+ switch (p_flow_req->key.flow_type)
+ {
+ /* unicast flows */
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ {
+ if (p_flow_req->data.classifier.o_pbits)
+ {
+ /* o_pbits can only take one p-bit value */
+ pbits_val = p_flow_req->data.classifier.o_pbits;
+ }
+ else
+ {
+ pbits_val = 0;
+ }
+
+ /* create a gem port id and relevant flow for a single pbit, or with no pbit */
+ /* pass on the op type also to specify if it is FLOW_ADD OR FLOW_MODIFY */
+ rc = maple_mac_unicast_flow_add(p_flow_req, pbits_val, per_flow_mode_vlan_id, op_type, &p_mac_util_flow_entry);
+ if ((BCM_ERR_OK != rc) || (NULL == p_mac_util_flow_entry))
+ {
+ break;
+ }
+
+ /* mark flow configuration to device completed */
+ mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
+ rc = maple_mac_xgpon_update_svc_port_ind_flag (p_flow_req, p_mac_util_flow_entry);
+
+ }
+ break;
+
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ {
+ rc = maple_mac_broadcast_flow_add(p_flow_req, per_flow_mode_vlan_id, op_type, &p_mac_util_flow_entry);
+ }
+ break;
+
+ default:
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unknown flow type %d\n",
+ p_flow_req->key.flow_type);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else if ((BAL_UTIL_OPER_FLOW_REMOVE == op_type) ||
+ (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
+ {
+ /* find the flow */
+ p_mac_util_flow_entry = _mac_util_db_flow_get_w_flow_key(p_flow_req->data.access_int_id, &(p_flow_req->key));
+ if (NULL == p_mac_util_flow_entry)
+ {
+ rc = BCM_ERR_NOENT;
+ if (BAL_UTIL_OPER_FLOW_CLEAR != op_type)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "%s: NULL mac util flow entry to remove: flow id: %d, flow_type: %s\n",
+ __FUNCTION__,
+ p_flow_req->key.flow_id,
+ (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ? "up":"down"));
+ }
+
+ goto exit;
+ }
+
+ switch (p_flow_req->key.flow_type)
+ {
+ /* unicast flows */
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ {
+ /** Remove unicast GEM/Alloc Id from Maple and flow entry from local database */
+ rc = maple_mac_unicast_flow_remove(p_flow_req, op_type, p_mac_util_flow_entry);
+ if (BCM_ERR_OK != rc)
+ {
+ break;
+ }
+
+ /* mark flow De-configuration to device completed */
+ mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
+ }
+ break;
+
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ {
+ rc = maple_mac_broadcast_flow_remove(p_flow_req, per_flow_mode_vlan_id, op_type, p_mac_util_flow_entry);
+ }
+ break;
+
+ default:
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unknown flow type %d\n",
+ p_flow_req->key.flow_type);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+
+ } /* Flow Remove */
+ else
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
+ "Unknown flow op type %d for flow id/type = %d/%d\n",
+ op_type, p_flow_req->key.flow_id, p_flow_req->key.flow_type);
+ rc = BCM_ERR_PARM;
+ }
+
+exit:
+ if (BCM_ERR_OK == rc)
+ {
+ /*
+ * Check flow entry flags to see if an indication to Core should be triggered immediately:
+ * (Special handling for flow configuration, for the case no device configuration is needed,
+ * and/or no indication from device is expected - could be the case of a single/multiple
+ * gem ports used for us and ds, and us was already configured.
+ * - send the flow ind immediately
+ */
+ check_send_flow_bal_ind_msg(p_mac_util_flow_entry, BCM_ERR_OK, BCMOLT_RESULT_SUCCESS);
+ }
+ else
+ {
+ if ((BCM_ERR_NOENT == rc) && (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
+ {
+ /*
+ * For flow CLEAR, and if no flow entry is found, then fake an indication success to Core,
+ * for it to execute the flow state machine.
+ * The reasons for flow entry not found could be because the flow was already admin-ed Down.
+ * Admin-down of a flow causes mac util to clear flow config and flow instance from itself
+ * and the maple HW. However, Core FSM still keeps it's flow instance during admin down state.
+ */
+ mac_util_report_flow_remove_success (p_flow_req->key, p_flow_req->data.access_int_id, op_type);
+ rc = BCM_ERR_OK;
+ }
+ }
+ //else if there was an error during config, just return a failure; no need to send back indication for that.
+
+
+ return rc;
+}
+
+bcmos_errno maple_xgpon_mac_check_gem_port_id(uint32_t if_id, uint32_t onu_id, uint16_t svc_port_id,
+ bcmos_bool *is_configured, bcmos_bool *is_activated)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_gem_port_key gem_key = {};
+ bcmolt_xgpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the gem port object key */
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, xgpon_gem_port, gem_key);
+ BCMOLT_CFG_PROP_GET(&gem_cfg, xgpon_gem_port, all_properties);
+
+ rc = bcmolt_cfg_get(device_id, &gem_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED to gem xgpon_gem_port configuration : device_id = %d if_id = %d gem_port_id = %d \n",
+ __FUNCTION__,
+ device_id, if_id, svc_port_id);
+ return rc;
+ }
+
+ /* may be configured; does gem belong to same onu ? */
+ if (BCMOLT_XGPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state && onu_id != gem_cfg.data.onu_id)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED, onu id mismatch: svc_port_id = %d if_id = %d is already assigned to onu_id = %d (not to onu id %d) \n",
+ __FUNCTION__,
+ svc_port_id, if_id, gem_cfg.data.onu_id, onu_id);
+ return BCM_ERR_PARM;
+ }
+ *is_configured = BCMOLT_XGPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state;
+ *is_activated = BCMOLT_XGPON_GEM_PORT_STATE_ACTIVE == gem_cfg.data.gem_port_state;
+
+ return rc;
+}
+
+
+bcmos_errno maple_xgpon_gem_port_id_add(uint32_t if_id, uint16_t svc_port_id, uint32_t onu_id, bcmolt_gem_port_configuration *configuration)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_gem_port_key gem_key = {};
+ bcmolt_xgpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the gem port object key */
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, xgpon_gem_port, gem_key);
+
+ /* set the gem port configuration */
+ if (onu_id < BCMOLT_XGPON_ONU_ID_ANY)
+ {
+ BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, onu_id, onu_id);
+ BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, upstream_destination_queue,
+ BCMOLT_US_GEM_PORT_DESTINATION_DATA);
+ }
+ BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, encryption_mode,
+ BCMOLT_CONTROL_STATE_DISABLE);
+ BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, configuration, *configuration);
+ BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, control, BCMOLT_CONTROL_STATE_ENABLE);
+
+ rc = bcmolt_cfg_set(device_id, &gem_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED: rc=%s (%d), svc_port_id = %d if_id = %d onu_id = %d, err_text=%s\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), rc, svc_port_id, if_id, onu_id, gem_cfg.hdr.hdr.err_text);
+ }
+
+ return rc;
+}
+
+
+bcmos_errno maple_xgpon_gem_port_id_remove(uint32_t if_id, uint16_t svc_port_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_gem_port_key gem_key = {};
+ bcmolt_xgpon_gem_port_cfg gem_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ gem_key.pon_ni = physical_if_id;
+ gem_key.gem_port_id = svc_port_id;
+ BCMOLT_CFG_INIT(&gem_cfg, xgpon_gem_port, gem_key);
+ rc = bcmolt_cfg_clear(device_id, &gem_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ }
+
+ return rc;
+}
+
+
+bcmos_errno maple_xgpon_mac_get_alloc_id_config (uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_alloc_state *alloc_id_state)
+
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_alloc_key alloc_key = {};
+ bcmolt_xgpon_alloc_cfg alloc_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the alloc-id key */
+ alloc_key.pon_ni = physical_if_id;
+ alloc_key.alloc_id = agg_id;
+ BCMOLT_CFG_INIT(&alloc_cfg, xgpon_alloc, alloc_key);
+ BCMOLT_CFG_PROP_GET(&alloc_cfg, xgpon_alloc, all_properties);
+
+ rc = bcmolt_cfg_get(device_id, &alloc_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s: FAILED in bcmolt_cfg_get rc = %s, agg_id = %d if_id = %d\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), agg_id, if_id);
+
+ return rc;
+ }
+
+ /* may be configured; does alloc id belong to the expected onu ? */
+ if (alloc_cfg.data.state != BCMOLT_ALLOC_STATE_NOT_CONFIGURED
+ && alloc_cfg.data.onu_id != onu_id)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s FAILED, onu id mismatch: agg_id = %d if_id = %d is set to onu %d NOT to onu_id = %d\n",
+ __FUNCTION__,
+ agg_id, if_id, alloc_cfg.data.onu_id, onu_id);
+
+ return BCM_ERR_PARM;
+ }
+ *alloc_id_state = alloc_cfg.data.state;
+
+ return BCM_ERR_OK;
+}
+
+
+bcmos_errno maple_xgpon_us_alloc_id_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla agg_sla)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_alloc_key alloc_key = {};
+ bcmolt_xgpon_alloc_cfg alloc_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+
+ /* set the alloc-id key */
+ alloc_key.pon_ni = physical_if_id;
+ alloc_key.alloc_id = agg_id;
+ BCMOLT_CFG_INIT(&alloc_cfg, xgpon_alloc, alloc_key);
+
+ BCMOLT_CFG_PROP_SET(&alloc_cfg, xgpon_alloc, sla, agg_sla);
+ /* set the alloc-id - onu assignment */
+ BCMOLT_CFG_PROP_SET(&alloc_cfg, xgpon_alloc, onu_id, onu_id);
+
+ rc = bcmolt_cfg_set(device_id, &alloc_cfg.hdr);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "%s: rc = %s, agg_id = %d if_id = %d, sla = {g bw: %d, max bw: %d, cb_nrt_bw: %d, cb_rt_bw: %d}\n",
+ __FUNCTION__,
+ bcmos_strerror(rc), agg_id, if_id,
+ agg_sla.guaranteed_bw, agg_sla.maximum_bw, agg_sla.cbr_nrt_bw, agg_sla.cbr_rt_bw);
+
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
+ "err_text = %s\n",
+ alloc_cfg.hdr.hdr.err_text);
+ }
+ return rc;
+}
+
+
+bcmos_errno maple_xgpon_us_alloc_id_remove(uint32_t if_id, uint16_t agg_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcmolt_xgpon_alloc_key alloc_key = {};
+ bcmolt_xgpon_alloc_cfg alloc_cfg = {};
+ bcmolt_devid device_id;
+ uint32_t physical_if_id;
+
+ GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
+
+ /* set the alloc-id key */
+ alloc_key.pon_ni = physical_if_id;
+ alloc_key.alloc_id = agg_id;
+ BCMOLT_CFG_INIT(&alloc_cfg, xgpon_alloc, alloc_key);
+
+ rc = bcmolt_cfg_clear(device_id, &alloc_cfg.hdr);
+ if (BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
+ }
+ return rc;
+}
+
+/**
+ * @brief group set for xgpon (XG-PON1)
+ * @param p_group_req pointer to group request structure from core
+ * @param op_type ADD, REMOVE or SET
+ * @param p_group_inst pointer to the Core Group Object instance
+ *
+ * @return errno error
+ *
+ * @todo shift this out to mac specific files
+ */
+bcmos_errno mac_util_group_set_for_xgpon (bcmbal_group_cfg *p_group_req, bal_util_oper_group op_type, group_inst *p_group_inst)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ uint16_t svc_port_id;
+ uint32_t if_id, i, ref_count;
+ bcmolt_gem_port_configuration configuration = {0};
+
+ /* Check the operation id */
+ if ((BAL_UTIL_OPER_GROUP_ADD != op_type) &&
+ (BAL_UTIL_OPER_GROUP_REMOVE != op_type) &&
+ (BAL_UTIL_OPER_GROUP_SET != op_type))
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "Unexpected mac_util xgpon group operation %d \n", op_type);
+ return BCM_ERR_PARM;
+ }
+
+ configuration.direction = BCMOLT_GEM_PORT_DIRECTION_DOWNSTREAM;
+ configuration.type = BCMOLT_GEM_PORT_TYPE_MULTICAST;
+
+ /* for group SET operation, first remove the old multicast GEM */
+ if (BAL_UTIL_OPER_GROUP_SET == op_type)
+ {
+ bcmbal_group_cfg *p_group_rem_req;
+ /* use the Core DB for existing members - store in current_flow_info */
+ p_group_rem_req = &p_group_inst->current_group_info;
+ for(i=0; i< p_group_rem_req->data.members.len; i++)
+ {
+ if_id = p_group_rem_req->data.members.val[i].intf_id;
+ svc_port_id = p_group_rem_req->data.members.val[i].svc_port_id;
+ /* svc_port_id may be 0 in the current info when the group had no owner.
+ skip the remove if that is the case */
+ if(svc_port_id)
+ {
+ rc = rsc_mgr_gem_get_ref_count(if_id, svc_port_id, &ref_count);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util xgpon group get reference count on interface %d (gem %d) failed \n", if_id, svc_port_id);
+ return rc;
+ }
+ /* if other group is referencing the same GEM (ref_count > 1), do not call Mac API to remove it.
+ The core will ask Resource Manger to decrease the counter if everything is good */
+ if ( ref_count == 1)
+ {
+ rc = maple_xgpon_gem_port_id_remove(if_id, svc_port_id);
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util xgpon group set operation SET on remove interface %d (gem %d) failed \n", if_id, svc_port_id);
+ return rc;
+ }
+ }
+ else if ( ref_count == 0)
+ {
+ BCM_LOG(WARNING, log_id_mac_util,
+ "mac_util xgpon group operation SET on interface %d (gem %d) remove with 0 reference count \n", if_id, svc_port_id);
+ }
+ }
+ }
+ }
+
+ /* walk through every member interface */
+ for(i=0; i< p_group_req->data.members.len; i++)
+ {
+ if_id = p_group_req->data.members.val[i].intf_id;
+ svc_port_id = p_group_req->data.members.val[i].svc_port_id;
+ /* group Add */
+ if (BAL_UTIL_OPER_GROUP_ADD == op_type || BAL_UTIL_OPER_GROUP_SET == op_type)
+ {
+ rc = maple_xgpon_gem_port_id_add(if_id, svc_port_id, MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM, &configuration);
+ }
+ else if (BAL_UTIL_OPER_GROUP_REMOVE == op_type)
+ {
+ rc = rsc_mgr_gem_get_ref_count(if_id, svc_port_id, &ref_count);
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util xgpon group REM get reference count on interface %d (gem %d) failed \n", if_id, svc_port_id);
+ break;
+ }
+ /* if other group is referencing the same GEM (ref_count > 1), do not call Mac API to remove it.
+ The core will ask Resource Manger to decrease the counter if everything is good */
+ if ( ref_count == 1)
+ {
+ rc = maple_xgpon_gem_port_id_remove(if_id, svc_port_id);
+ }
+ else if ( ref_count == 0)
+ {
+ BCM_LOG(WARNING, log_id_mac_util,
+ "mac_util xgpon group operation REM on interface %d (gem %d) remove with 0 reference count \n", if_id, svc_port_id);
+ }
+ }
+
+ if(BCM_ERR_OK != rc)
+ {
+ BCM_LOG(ERROR, log_id_mac_util,
+ "mac_util xgpon group set of operation %d on interface %d (gem %d) failed \n", op_type, if_id, svc_port_id);
+ break;
+ }
+ }
+
+ return rc;
+}
+
+
+/*@}*/
diff --git a/bal_release/src/core/util/oam/Makefile b/bal_release/src/core/util/oam/Makefile
new file mode 100644
index 0000000..e87d3a4
--- /dev/null
+++ b/bal_release/src/core/util/oam/Makefile
@@ -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.
+#
+# :>
+#
+###############################################################################
+# BAL core CLI application
+#
+MOD_NAME = bal_oam_util
+MOD_TYPE = lib
+MOD_DEPS = maple_sdk bcm_user_appl_epon_oam bcm_user_appl_eon
+
+srcs = bal_oam_util.c
+
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../main
+
diff --git a/bal_release/src/core/util/oam/bal_oam_util.c b/bal_release/src/core/util/oam/bal_oam_util.c
new file mode 100644
index 0000000..fe051f9
--- /dev/null
+++ b/bal_release/src/core/util/oam/bal_oam_util.c
@@ -0,0 +1,459 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_oam_util.c
+ *
+ * @brief OAM util interfaces definition used by Bal Core
+ *
+ * This file expose the APIs to the core to configure ONU via EPON OAM
+ *
+ * @addtogroup oam_util
+ */
+
+/*@{*/
+
+#include "bal_oam_util.h"
+#include <bcmolt_user_appl_epon_oam.h>
+#include <bcmolt_eon.h>
+#include <bcmolt_eon_log.h>
+#include <bcmolt_epon_oam_types.h>
+
+#define BAL_OAM_TIMEOUT_US 1000000 /* 1 second */
+
+typedef enum
+{
+ BAL_OAM_STATE_IDLE,
+ BAL_OAM_STATE_SET_OAM_RATE,
+ BAL_OAM_STATE_CLEAR_INGRESS_RULES_NETWORK_PON,
+ BAL_OAM_STATE_CLEAR_INGRESS_RULES_USER_PORT,
+ BAL_OAM_STATE_SET_BASIC_QUEUE_CONFIG,
+ BAL_OAM_STATE_ADD_INGRESS_RULES_NETWORK_PON,
+ BAL_OAM_STATE_ADD_INGRESS_RULES_USER_PORT,
+ BAL_OAM_STATE_SET_REPORT_THRESHOLDS,
+ BAL_OAM_STATE_ENABLE_USER_TRAFFIC,
+ BAL_OAM_STATE_DISABLE_USER_TRAFFIC,
+ BAL_OAM_STATE__NUM_OF,
+} bal_oam_state;
+
+typedef enum
+{
+ BAL_OAM_EVENT_ACK,
+ BAL_OAM_EVENT_TIMEOUT,
+ BAL_OAM_EVENT__NUM_OF,
+} bal_oam_event;
+
+typedef struct bal_oam_context
+{
+ TAILQ_ENTRY(bal_oam_context) next;
+ bal_oam_cb cb;
+ void *context;
+ bcmolt_devid device_id;
+ bcmolt_epon_ni epon_ni;
+ bcmos_mac_address mac;
+ bcmos_timer timer;
+ bal_oam_state state;
+} bal_oam_context;
+
+typedef struct
+{
+ bcmos_msg m;
+ bcmolt_devid device_id;
+ bcmolt_epon_ni epon_ni;
+ bcmos_mac_address mac;
+} bal_oam_timeout_msg;
+
+typedef bcmos_errno (*bal_oam_sm_cb)(bal_oam_context *context);
+
+static TAILQ_HEAD(, bal_oam_context) bal_oam_contexts = TAILQ_HEAD_INITIALIZER(bal_oam_contexts);
+
+static bal_oam_context *bal_oam_get_context(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac)
+{
+ bal_oam_context *iter;
+
+ TAILQ_FOREACH(iter, &bal_oam_contexts, next)
+ {
+ if (device_id == iter->device_id && epon_ni == iter->epon_ni && !memcmp(mac, &iter->mac, sizeof(*mac)))
+ break;
+ }
+ return iter;
+}
+
+static void bal_oam_negotiation_result_cb(void *context, const eon_link_key_t *link_key, bcmos_errno result)
+{
+ bal_oam_context *_context = context;
+
+ _context->cb(_context->context, _context->device_id, _context->epon_ni, &_context->mac, result);
+
+ bcmos_free(_context);
+}
+
+bcmos_errno bal_oam_start_oam_negotiation(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, bcmos_mac_address *mac, bal_oam_cb cb, void *context)
+{
+ eon_link_key_t link_key = {};
+ bal_oam_context *_context;
+
+ link_key.device_id = device_id;
+ link_key.epon_ni = epon_ni;
+ link_key.mac_address = *mac;
+
+ _context = bcmos_calloc(sizeof(*_context));
+ _context->cb = cb;
+ _context->context = context;
+ _context->device_id = device_id;
+ _context->epon_ni = epon_ni;
+ _context->mac = *mac;
+
+ return bcmolt_user_appl_eon_start(&link_key, eon_oam_set_id_dpoe, bal_oam_negotiation_result_cb, _context, BCMOS_TRUE);
+}
+
+static void bal_oam_configure_traffic_complete(bal_oam_context *context, bcmos_errno result)
+{
+ context->cb(context->context, context->device_id, context->epon_ni, &context->mac, result);
+
+ bcmos_timer_destroy(&context->timer);
+
+ TAILQ_REMOVE(&bal_oam_contexts, context, next);
+
+ /* No need to set context->state to BAL_OAM_STATE_IDLE - it is going to be destroyed here anyway. */
+ bcmos_free(context);
+}
+
+static void bal_oam_timeout_msg_cb(bcmos_module_id module_id, bcmos_msg *msg)
+{
+ bal_oam_timeout_msg *timeout_msg = (bal_oam_timeout_msg *)msg;
+ bal_oam_context *context = bal_oam_get_context(timeout_msg->device_id, timeout_msg->epon_ni, &timeout_msg->mac);
+
+ bal_oam_configure_traffic_complete(context, BCM_ERR_TIMEOUT);
+
+ bcmos_msg_free(msg);
+}
+
+static bcmos_errno bal_oam_state_any_event_timeout(bal_oam_context *context)
+{
+ bal_oam_timeout_msg *msg;
+
+ /* We should not directly call bal_oam_configure_traffic_complete() from within timer context, because in bal_oam_configure_traffic_complete() we free the memory in which the timer
+ * resides. To overcome this, we use a message - the timer will finish executing and only then the message handler will execute. */
+ msg = bcmos_calloc(sizeof(*msg));
+ msg->device_id = context->device_id;
+ msg->epon_ni = context->epon_ni;
+ msg->mac = context->mac;
+ msg->m.handler = bal_oam_timeout_msg_cb;
+ bcmos_msg_send_to_module(BCMOS_MODULE_ID_WORKER_MGMT, &msg->m, 0);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_set_oam_rate_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+
+ /* Clear EPON port ingress. */
+ rc = epon_oam_dpoe_clear_ingress_rules_network_pon(context->device_id, context->epon_ni, &context->mac);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_CLEAR_INGRESS_RULES_NETWORK_PON;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_clear_ingress_rules_network_pon_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+
+ /* Clear UNI port ingress rules. */
+ rc = epon_oam_dpoe_clear_ingress_rules_user_port(context->device_id, context->epon_ni, &context->mac);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_CLEAR_INGRESS_RULES_USER_PORT;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_clear_ingress_rules_user_port_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+
+ /* Set ONU queue configuration. */
+ rc = epon_oam_dpoe_set_basic_queue_config(context->device_id, context->epon_ni, &context->mac, 255, 255);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_SET_BASIC_QUEUE_CONFIG;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_set_basic_queue_config_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+
+ /* Add EPON port ingress rules */
+ rc = epon_oam_dpoe_add_ingress_rules_network_pon(context->device_id, context->epon_ni, &context->mac, DPOE_RULE_VLAN_MODE_NONE, NULL);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_ADD_INGRESS_RULES_NETWORK_PON;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_add_ingress_rules_network_pon_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+
+ /* Add UNI port ingress rules. */
+ rc = epon_oam_dpoe_add_ingress_rules_user_port(context->device_id, context->epon_ni, &context->mac, DPOE_RULE_VLAN_MODE_NONE, NULL);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_ADD_INGRESS_RULES_USER_PORT;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_add_ingress_rules_user_port_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+ bcmolt_epon_oam_queue_sets queue_sets =
+ {
+ [0] = {16256},
+ [1] = {32512},
+ [2] = {48768},
+ [3] = {65024},
+ };
+
+ /* Set ONU report thresholds. */
+ rc = epon_oam_dpoe_set_report_thresholds(context->device_id, context->epon_ni, &context->mac, 1, queue_sets, 4);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_SET_REPORT_THRESHOLDS;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_set_report_thresholds_event_ack(bal_oam_context *context)
+{
+ bcmos_errno rc;
+
+ /* Enable user traffic. */
+ rc = epon_oam_dpoe_enable_user_traffic(context->device_id, context->epon_ni, &context->mac);
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(context, rc);
+ return rc;
+ }
+
+ bcmos_timer_start(&context->timer, BAL_OAM_TIMEOUT_US);
+
+ context->state = BAL_OAM_STATE_ENABLE_USER_TRAFFIC;
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_enable_user_traffic_event_ack(bal_oam_context *context)
+{
+ bal_oam_configure_traffic_complete(context, BCM_ERR_OK);
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_oam_state_disable_user_traffic_event_ack(bal_oam_context *context)
+{
+ bal_oam_configure_traffic_complete(context, BCM_ERR_OK);
+
+ return BCM_ERR_OK;
+}
+
+static bal_oam_sm_cb bal_oam_state_machine[BAL_OAM_STATE__NUM_OF][BAL_OAM_EVENT__NUM_OF] =
+{
+ [BAL_OAM_STATE_SET_OAM_RATE] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_set_oam_rate_event_ack,
+ },
+ [BAL_OAM_STATE_CLEAR_INGRESS_RULES_NETWORK_PON] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_clear_ingress_rules_network_pon_event_ack,
+ },
+ [BAL_OAM_STATE_CLEAR_INGRESS_RULES_USER_PORT] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_clear_ingress_rules_user_port_event_ack,
+ },
+ [BAL_OAM_STATE_SET_BASIC_QUEUE_CONFIG] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_set_basic_queue_config_event_ack,
+ },
+ [BAL_OAM_STATE_ADD_INGRESS_RULES_NETWORK_PON] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_add_ingress_rules_network_pon_event_ack,
+ },
+ [BAL_OAM_STATE_ADD_INGRESS_RULES_USER_PORT] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_add_ingress_rules_user_port_event_ack,
+ },
+ [BAL_OAM_STATE_SET_REPORT_THRESHOLDS] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_set_report_thresholds_event_ack,
+ },
+ [BAL_OAM_STATE_ENABLE_USER_TRAFFIC] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_enable_user_traffic_event_ack,
+ },
+ [BAL_OAM_STATE_DISABLE_USER_TRAFFIC] =
+ {
+ [BAL_OAM_EVENT_TIMEOUT] = bal_oam_state_any_event_timeout,
+ [BAL_OAM_EVENT_ACK] = bal_oam_state_disable_user_traffic_event_ack,
+ },
+};
+
+static void bal_oam_sm_run(bal_oam_context *context, bal_oam_event event)
+{
+ bal_oam_sm_cb cb = bal_oam_state_machine[context->state][event];
+
+ cb(context);
+}
+
+static bcmos_timer_rc bal_oam_timeout_cb(bcmos_timer *timer, long data)
+{
+ bal_oam_context *context = (bal_oam_context *)data;
+
+ bal_oam_sm_run(context, BAL_OAM_EVENT_TIMEOUT);
+
+ return BCMOS_TIMER_OK;
+}
+
+bcmos_errno bal_oam_configure_traffic(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, bcmos_mac_address *mac, bcmos_bool is_enabled, bal_oam_cb cb, void *context)
+{
+ bcmos_errno rc;
+ bal_oam_context *_context;
+ bcmos_timer_parm timer_params =
+ {
+ .name = "bal_oam_timer",
+ .owner = BCMOS_MODULE_ID_WORKER_MGMT,
+ .handler = bal_oam_timeout_cb,
+ };
+
+ _context = bcmos_calloc(sizeof(*_context));
+ _context->cb = cb;
+ _context->context = context;
+ _context->device_id = device_id;
+ _context->epon_ni = epon_ni;
+ _context->mac = *mac;
+ TAILQ_INSERT_TAIL(&bal_oam_contexts, _context, next);
+
+ if (is_enabled)
+ {
+ /* Set OAM rate. */
+ rc = epon_oam_dpoe_set_oam_rate(device_id, epon_ni, mac, 10, 3);
+ }
+ else
+ {
+ /* Disable user traffic. */
+ rc = epon_oam_dpoe_disable_user_traffic(device_id, epon_ni, mac);
+ }
+ if (rc != BCM_ERR_OK)
+ {
+ bal_oam_configure_traffic_complete(_context, rc);
+ return rc;
+ }
+
+ timer_params.data = (long)_context;
+ bcmos_timer_create(&_context->timer, &timer_params);
+ bcmos_timer_start(&_context->timer, BAL_OAM_TIMEOUT_US);
+
+ if (is_enabled)
+ _context->state = BAL_OAM_STATE_SET_OAM_RATE;
+ else
+ _context->state = BAL_OAM_STATE_DISABLE_USER_TRAFFIC;
+
+ return BCM_ERR_OK;
+}
+
+/* TODO: Currently we ignore rc. But we may want to check it. */
+void bal_oam_proxy_rx_cb(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac, bcmolt_user_appl_epon_oam_rx_id id, bcmos_errno rc)
+{
+ bal_oam_context *context;
+
+ if (id != BCMOLT_USER_APPL_EPON_OAM_RX_ID_DPOE_SET_RESPONSE)
+ return;
+
+ /* If applying set command not from within bal_oam_configure_traffic() (for example, from BAL CLI), context might be NULL. */
+ context = bal_oam_get_context(device_id, epon_ni, mac);
+ if (!context)
+ return;
+
+ bal_oam_sm_run(context, BAL_OAM_EVENT_ACK);
+}
+
+/*@}*/
+
diff --git a/bal_release/src/core/util/oam/bal_oam_util.h b/bal_release/src/core/util/oam/bal_oam_util.h
new file mode 100644
index 0000000..69af195
--- /dev/null
+++ b/bal_release/src/core/util/oam/bal_oam_util.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_oam_util.h
+ *
+ * @brief OAM util interfaces header file
+ *
+ * This file expose the APIs to the core to configure ONU via EPON OAM
+ *
+ * @defgroup oam_util OAM Util
+ * @ingroup core
+ */
+
+#ifndef BAL_OAM_UTIL_H
+#define BAL_OAM_UTIL_H
+
+#include <bcmolt_host_api.h>
+#include <bcmolt_user_appl_epon_oam.h>
+
+typedef void (*bal_oam_cb)(void *context, bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac_address, bcmos_errno result);
+
+/*****************************************************************************/
+/**
+ * @brief Start OAM negotiation for a given MAC address.
+ *
+ * @param device_id Device ID for which we start OAM negotiation
+ * @param epon_ni EPON NI for which we start OAM negotiation
+ * @param mac MAC address for which we start OAM negotiation
+ * @param cb Callback called upon completion, with success or failure
+ * code. If omitted, a default callback will be called and
+ * it will just log the return code
+ * @param context context for the above callback
+ *
+ * @returns BCM_ERR_OK on success, other bcmos_errno codes otherwise
+ *
+ *****************************************************************************/
+bcmos_errno bal_oam_start_oam_negotiation(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, bcmos_mac_address *mac, bal_oam_cb cb, void *context);
+
+/*****************************************************************************/
+/**
+ * @brief Enable traffic for a given MAC address.
+ *
+ * @param device_id Device ID for which we enable/disable traffic
+ * @param epon_ni EPON NI for which we enable/disable traffic
+ * @param mac MAC address for which we enable/disable traffic
+ * @param is_enabled Whether we should enable or disable traffic
+ * @param cb Callback called upon completion, with success or failure
+ * code. If omitted, a default callback will be called and
+ * it will just log the return code
+ * @param context context for the above callback
+ *
+ * @returns BCM_ERR_OK on success, other bcmos_errno codes otherwise
+ *
+ *****************************************************************************/
+bcmos_errno bal_oam_configure_traffic(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, bcmos_mac_address *mac, bcmos_bool is_enabled, bal_oam_cb cb, void *context);
+
+/*****************************************************************************/
+/**
+ * @brief Callback being called whenever an OAM message (proxy rx) arrives and
+ * processed by bcmolt_user_appl_epon_oam_handle_proxy_rx().
+ *
+ * @param device_id Device ID for which we got the message
+ * @param epon_ni EPON NI for which we got the message
+ * @param mac MAC address for which we got the message
+ * @param id The type of message
+ * @param rc OAM response success/fail code
+ *
+ *****************************************************************************/
+void bal_oam_proxy_rx_cb(bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac, bcmolt_user_appl_epon_oam_rx_id id, bcmos_errno rc);
+
+#endif
+
diff --git a/bal_release/src/core/util/oam/common_epon_oam b/bal_release/src/core/util/oam/common_epon_oam
new file mode 120000
index 0000000..5376be7
--- /dev/null
+++ b/bal_release/src/core/util/oam/common_epon_oam
@@ -0,0 +1 @@
+../../../../3rdparty/maple/sdk/host_reference/common_epon_oam
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/Makefile b/bal_release/src/core/util/oam/eon/Makefile
new file mode 100644
index 0000000..bc94abe
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/Makefile
@@ -0,0 +1,57 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# EPON OAM Negotiation user application
+
+ifeq ("$(ENABLE_CLI)", "y")
+
+ MOD_NAME = bcm_user_appl_eon
+ MOD_TYPE = lib
+ MOD_DEPS = bal_api common_epon_oam bcm_user_appl_epon_oam
+
+ ifeq ("$(OS_KERNEL)", "linux")
+ MOD_DEPS += dev_log_linux
+ endif
+
+ srcs = bcmolt_eon.c bcmolt_eon_log.c bcmolt_oam_heartbeat.c
+
+ ENABLE_DPOE_OAM ?= y
+ ifeq ("$(ENABLE_DPOE_OAM)", "y")
+ EXTRA_DEFINES += -DEON_OAM_SET_DPOE_SUPPORTED
+ srcs += oam_sets/dpoe/dpoe.c
+ endif # ENABLE_DPOE_OAM
+
+ ENABLE_BRCM_OAM ?= y
+ ifeq ("$(ENABLE_BRCM_OAM)", "y")
+ EXTRA_DEFINES += -DEON_OAM_SET_BRCM_SUPPORTED
+ srcs += oam_sets/brcm/brcm.c
+ endif # ENABLE_BRCM_OAM
+
+endif
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_eon.c b/bal_release/src/core/util/oam/eon/bcmolt_eon.c
new file mode 120000
index 0000000..8f3003d
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_eon.c
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_eon.c
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_eon.h b/bal_release/src/core/util/oam/eon/bcmolt_eon.h
new file mode 120000
index 0000000..d7f8504
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_eon.h
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_eon.h
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_eon_log.c b/bal_release/src/core/util/oam/eon/bcmolt_eon_log.c
new file mode 120000
index 0000000..73c5c57
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_eon_log.c
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_eon_log.c
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_eon_log.h b/bal_release/src/core/util/oam/eon/bcmolt_eon_log.h
new file mode 120000
index 0000000..164ba04
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_eon_log.h
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_eon_log.h
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_eon_private.h b/bal_release/src/core/util/oam/eon/bcmolt_eon_private.h
new file mode 120000
index 0000000..3417ea1
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_eon_private.h
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_eon_private.h
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_oam_heartbeat.c b/bal_release/src/core/util/oam/eon/bcmolt_oam_heartbeat.c
new file mode 120000
index 0000000..ee96fc5
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_oam_heartbeat.c
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_oam_heartbeat.c
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/bcmolt_oam_heartbeat.h b/bal_release/src/core/util/oam/eon/bcmolt_oam_heartbeat.h
new file mode 120000
index 0000000..a45c1cd
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/bcmolt_oam_heartbeat.h
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/bcmolt_oam_heartbeat.h
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/doc b/bal_release/src/core/util/oam/eon/doc
new file mode 120000
index 0000000..9a076c6
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/doc
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/doc
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/eon/oam_sets b/bal_release/src/core/util/oam/eon/oam_sets
new file mode 120000
index 0000000..a9926e8
--- /dev/null
+++ b/bal_release/src/core/util/oam/eon/oam_sets
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/eon/oam_sets
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/epon_oam/Makefile b/bal_release/src/core/util/oam/epon_oam/Makefile
new file mode 100644
index 0000000..969352a
--- /dev/null
+++ b/bal_release/src/core/util/oam/epon_oam/Makefile
@@ -0,0 +1,42 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+ifeq ("$(ENABLE_CLI)", "y")
+ MOD_NAME = bcm_user_appl_epon_oam
+ MOD_TYPE = lib
+ MOD_DEPS = utils dev_log common_epon_oam bal_api
+
+ srcs = bcmolt_user_appl_epon_oam.c
+
+ ifeq ("$(OS_KERNEL)", "linux")
+ MOD_DEPS += dev_log_linux
+ endif
+endif
+
diff --git a/bal_release/src/core/util/oam/epon_oam/bcmolt_user_appl_epon_oam.c b/bal_release/src/core/util/oam/epon_oam/bcmolt_user_appl_epon_oam.c
new file mode 120000
index 0000000..90fbfee
--- /dev/null
+++ b/bal_release/src/core/util/oam/epon_oam/bcmolt_user_appl_epon_oam.c
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/epon_oam/bcmolt_user_appl_epon_oam.c
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/epon_oam/bcmolt_user_appl_epon_oam.h b/bal_release/src/core/util/oam/epon_oam/bcmolt_user_appl_epon_oam.h
new file mode 120000
index 0000000..ed97c3f
--- /dev/null
+++ b/bal_release/src/core/util/oam/epon_oam/bcmolt_user_appl_epon_oam.h
@@ -0,0 +1 @@
+../../../../../3rdparty/maple/sdk/host_reference/user_appl/epon_oam/bcmolt_user_appl_epon_oam.h
\ No newline at end of file
diff --git a/bal_release/src/core/util/oam/epon_oam_cli b/bal_release/src/core/util/oam/epon_oam_cli
new file mode 120000
index 0000000..f758382
--- /dev/null
+++ b/bal_release/src/core/util/oam/epon_oam_cli
@@ -0,0 +1 @@
+../../../../3rdparty/maple/sdk/host_reference/user_appl/epon_oam_cli
\ No newline at end of file
diff --git a/bal_release/src/core/util/switch/Makefile b/bal_release/src/core/util/switch/Makefile
new file mode 100644
index 0000000..d9f3aae
--- /dev/null
+++ b/bal_release/src/core/util/switch/Makefile
@@ -0,0 +1,46 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# BAL Switch Util
+MOD_NAME = bal_switch_util
+MOD_TYPE = lib
+MOD_DEPS = dev_log utils bal_api bal_app_utils switch_util_dpp switch_util_esw
+srcs = bal_switch_util.c bal_switch_acc_term.c bal_switch_flow.c bal_switch_cli.c bal_switch_interface.c bal_switch_group.c bal_switch_tm_sched.c bal_switch_tm_queue.c
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../main
+
+ifeq ("$(TEST_SW_UTIL_LOOPBACK)", "y")
+ MOD_DEFS += -DTEST_SW_UTIL_LOOPBACK
+else
+ MOD_DEPS += switch_sdk
+endif
+
+ifeq ("$(SWITCH)", "kt2")
+ MOD_DEFS += -DESW_SWITCH
+endif
diff --git a/bal_release/src/core/util/switch/bal_switch_acc_term.c b/bal_release/src/core/util/switch/bal_switch_acc_term.c
new file mode 100644
index 0000000..fb1be7b
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_acc_term.c
@@ -0,0 +1,1071 @@
+/******************************************************************************
+ *
+ * <: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 <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_util.h"
+#include "bal_switch_acc_term.h"
+#include "bal_switch_flow.h"
+#include <bal_worker.h>
+/* declare ENV so that the bcm/rx.h in the bal_dpp_acc_term.h can create the correct bcm_pkt_t structure */
+#ifdef ESW_SWITCH
+#define BCM_ESW_SUPPORT 1
+#else
+#define BCM_DNX_SUPPORT 1
+#endif
+#include "esw/bal_esw_acc_term.h"
+#include "dpp/bal_dpp_acc_term.h"
+/* Below local functions are used for real logic only */
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <arpa/inet.h>
+#include <bcm/init.h>
+#include <bcm/types.h>
+#include <bcm/port.h>
+#include <appl/diag/shell.h> /* for .soc loading */
+
+extern int socdiag_main(int argc, char *argv[]);
+
+/**
+ * @file bal_switch_acc_term.c
+ * @brief BAL Switch util functions that handle access terminal requests
+ * @addtogroup sw_util
+ *
+ */
+
+/*@{*/
+/* forward declaration */
+static void sw_util_bcm_rx_cb (int unit, int port, int reason, unsigned char *p_payload, int payload_len);
+
+/* define a customized dpp packetIn receive registration function.
+ * This function will be called when the HW trap a CPU bound packet
+ */
+static bcm_rx_t dpp_rx_cb_register(int unit, bcm_pkt_t *pkt, void *cookie)
+{
+ int src_port, reason_code, payload_len;
+ unsigned char *p_payload;
+
+ /* extract trap code, ingress port and payload info */
+ src_port = pkt->src_port & 0xff;
+ reason_code = pkt->rx_trap_data;
+ p_payload = pkt->_pkt_data.data + (pkt->tot_len - pkt->pkt_len);
+ payload_len = pkt->pkt_len;
+
+ /* call sw_util_bcm_rx_cb to send packet to the BAL client */
+ sw_util_bcm_rx_cb(unit, src_port, reason_code, p_payload, payload_len);
+ return BCM_RX_HANDLED;
+}
+
+/* The default switch device the switch app is managed */
+#ifdef CONFIG_SWITCH_RPC
+static uint32_t g_dft_dev_id = 2;
+#else
+static uint32_t g_dft_dev_id = 0;
+#endif
+static uint32_t g_iwf_mode = 0;
+static uint32_t g_l2_age_time = 300;
+
+/* flag to determine if we need RPC for switch communication */
+#ifdef CONFIG_SWITCH_RPC
+static uint32_t g_use_rpc = 1;
+#else
+static uint32_t g_use_rpc = 0;
+#endif
+
+/* Socket to be connected to the switch driver msg receiving UDP port */
+bcmos_bool g_pkt_send_is_initialized = BCMOS_FALSE;
+
+static trap_target s_target_device;
+
+/* Index to determine which interface mapping table should be used.
+ * The mapping table is HW specific and depend on how physical wires are lay out
+ * Any customized board may need a different table entry to reflect the connections
+ */
+static bal_swapp_port_map_indx g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON;
+
+ /* the logical interface to KT2 port mapping table
+ the tables is index by technology then logical interface number that used in the BAL CLI
+ the data is the switch port-bit-map number and device number
+*/
+
+/* table with gpon technology
+ based on KT2 port config option 4 - see page 22 on KT2 data sheet */
+/* gpon network interface mapping -
+ * KT2 is for Broadcom experiment purpose - not all function will work */
+bal_swapp_port net_inf_map_gpon[] = {
+ { 27, /* xe0 */ 0},
+ { 28, /* xe1 */ 0},
+ { 30, /* xe2 */ 0},
+ { 33, /* xe3 */ 0},
+ { 40, /* ge24 */ 0},
+ { -1, /* end */ 0}
+ };
+/* ARAD temp mapping xe128 - xe131 as nni ports */
+/* ARAD is for Broadcom experiment purpose - not all function will work */
+bal_swapp_port net_inf_map_exp[] = {
+ { 128, /* xe128 */ 0},
+ { 129, /* xe129 */ 0},
+ { 130, /* xe130 */ 0},
+ { 131, /* xe131 */ 0},
+ { -1, /* end */ 0}
+ };
+/* QAX temp mapping xe128-132 as nni ports 0-4 */
+bal_swapp_port net_inf_map_exp2[] = {
+ { 128, /* xe128 */ 0},
+ { 129, /* xe129 */ 0},
+ { 130, /* xe130 */ 0},
+ { 131, /* xe131 */ 0},
+ { 132, /* xe132 */ 0},
+ { -1, /* end */ 0}
+ };
+
+/* svk4 mapping xe128-133 as nni ports 0-5 */
+bal_swapp_port net_inf_map_svk4[] = {
+ { 128, /* xe128 */ 0},
+ { 129, /* xe129 */ 0},
+ { 130, /* xe130 */ 0},
+ { 131, /* xe131 */ 0},
+ { 132, /* xe132 */ 0},
+ { 133, /* xe133 */ 0},
+ { -1, /* end */ 0}
+ };
+
+/* epon 10g-capable mapping xe128-135 as nni ports 0-7 (best guess - needs to be tested) */
+bal_swapp_port net_inf_map_epon_tdma_10g[] = {
+ { 128, /* xe128 */ 0},
+ { 129, /* xe129 */ 0},
+ { 130, /* xe130 */ 0},
+ { 131, /* xe131 */ 0},
+ { 132, /* xe132 */ 0},
+ { 133, /* xe133 */ 0},
+ { 134, /* xe134 */ 0},
+ { 135, /* xe135 */ 0},
+ { -1, /* end */ 0}
+};
+
+/* epon 1g only mapping - copied from gpon KT2 example above (best guess - needs to be tested) */
+bal_swapp_port net_inf_map_epon_1g[] = {
+ { 27, /* xe0 */ 0},
+ { 28, /* xe1 */ 0},
+ { 30, /* xe2 */ 0},
+ { 33, /* xe3 */ 0},
+ { 40, /* ge24 */ 0},
+ { -1, /* end */ 0}
+};
+
+/* gpon pon interface mapping */
+bal_swapp_port pon_inf_map_gpon[] = {
+ { 5, /* ge4 */ 0},
+ { 6, /* ge5 */ 0},
+ { 2, /* ge1 */ 0},
+ { 1, /* ge0 */ 0},
+ { 8, /* ge7 */ 0},
+ { 7, /* ge6 */ 0},
+ { 4, /* ge3 */ 0},
+ { 3, /* ge2 */ 0},
+ { 12, /* ge11 */ 0},
+ { 19, /* ge18 */ 0},
+ { 10, /* ge9 */ 0},
+ { 15, /* ge14 */ 0},
+ { 11, /* ge10 */ 0},
+ { 17, /* ge16 */ 0},
+ { 9, /* ge8 */ 0},
+ { 13, /* ge12 */ 0},
+ { -1, /* end */ 0}
+ };
+bal_swapp_port pon_inf_map_gpon_v3[] = {
+ { 8, /* ge7 */ 0},
+ { 7, /* ge6 */ 0},
+ { 4, /* ge3 */ 0},
+ { 3, /* ge2 */ 0},
+ { 6, /* ge5 */ 0},
+ { 5, /* ge4 */ 0},
+ { 2, /* ge1 */ 0},
+ { 1, /* ge0 */ 0},
+ { 15, /* ge14 */ 0},
+ { 16, /* ge15 */ 0},
+ { 11, /* ge10 */ 0},
+ { 12, /* ge11 */ 0},
+ { 13, /* ge12 */ 0},
+ { 14, /* ge13 */ 0},
+ { 9, /* ge8 */ 0},
+ { 10, /* ge9 */ 0},
+ { -1, /* end */ 0}
+ };
+/* ARAD temp mapping xe0 - xe3 as PON ports */
+bal_swapp_port pon_inf_map_exp[] = {
+ { 0, /* xe0 */ 0},
+ { 1, /* xe1 */ 0},
+ { 2, /* xe2 */ 0},
+ { 3, /* xe3 */ 0},
+ { -1, /* end */ 0}
+ };
+/* QAX temp mapping xe1-6, as PON ports 0-5 */
+bal_swapp_port pon_inf_map_exp2[] = {
+ { 1, /* xe1 */ 0},
+ { 2, /* xe2 */ 0},
+ { 3, /* xe3 */ 0},
+ { 4, /* xe4 */ 0},
+ { 5, /* xe5 */ 0},
+ { 6, /* xe6 */ 0},
+ { -1, /* end */ 0}
+ };
+
+/* svk4 mapping xe1-4, as PON ports 0-3 */
+bal_swapp_port pon_inf_map_svk4[] = {
+ { 1, /* xe1 */ 0},
+ { 2, /* xe2 */ 0},
+ { 3, /* xe3 */ 0},
+ { 4, /* xe4 */ 0},
+ { -1, /* end */ 0}
+ };
+
+/* epon 10g-capable mapping xe1-8, as PON ports 0-7 (best guess - untested) */
+bal_swapp_port pon_inf_map_epon_tdma_10g[] = {
+ { 1, /* xe1 */ 0},
+ { 2, /* xe2 */ 0},
+ { 3, /* xe3 */ 0},
+ { 4, /* xe4 */ 0},
+ { 5, /* xe5 */ 0},
+ { 6, /* xe6 */ 0},
+ { 7, /* xe7 */ 0},
+ { 8, /* xe8 */ 0},
+ { -1, /* end */ 0}
+};
+
+/* epon 1g mapping xe1-16, as PON ports 0-15 (best guess - untested) */
+bal_swapp_port pon_inf_map_epon_1g[] = {
+ { 1, /* xe1 */ 0},
+ { 2, /* xe2 */ 0},
+ { 3, /* xe3 */ 0},
+ { 4, /* xe4 */ 0},
+ { 5, /* xe5 */ 0},
+ { 6, /* xe6 */ 0},
+ { 7, /* xe7 */ 0},
+ { 8, /* xe8 */ 0},
+ { 9, /* xe9 */ 0},
+ { 10, /* xe10 */ 0},
+ { 11, /* xe11 */ 0},
+ { 12, /* xe12 */ 0},
+ { 13, /* xe13 */ 0},
+ { 14, /* xe14 */ 0},
+ { 15, /* xe15 */ 0},
+ { 16, /* xe16 */ 0},
+ { -1, /* end */ 0}
+};
+
+/* network interface mapping table */
+bal_swapp_port *g_net_inf_map_table[BAL_SWAPP_PORT_MAP__NUM_OF] = {
+ net_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON */
+ net_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON_V3 */
+ net_inf_map_exp, /* BAL_SWAPP_PORT_MAP_EXP */
+ net_inf_map_exp2, /* BAL_SWAPP_PORT_MAP_EXP2 */
+ net_inf_map_svk4, /* BAL_SWAPP_PORT_MAP_SVK4 */
+ net_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
+ net_inf_map_epon_1g, /* BAL_SWAPP_PORT_MAP_EPON_1G */
+ net_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_10G */
+};
+/* pon interface mapping table */
+bal_swapp_port *g_pon_inf_map_table[BAL_SWAPP_PORT_MAP__NUM_OF] = {
+ pon_inf_map_gpon, /* BAL_SWAPP_PORT_MAP_GPON */
+ pon_inf_map_gpon_v3, /* BAL_SWAPP_PORT_MAP_GPON_V3 */
+ pon_inf_map_exp, /* BAL_SWAPP_PORT_MAP_EXP */
+ pon_inf_map_exp2, /* BAL_SWAPP_PORT_MAP_EXP2 */
+ pon_inf_map_svk4, /* BAL_SWAPP_PORT_MAP_SVK4 */
+ pon_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
+ pon_inf_map_epon_1g, /* BAL_SWAPP_PORT_MAP_EPON_1G */
+ pon_inf_map_epon_tdma_10g, /* BAL_SWAPP_PORT_MAP_EPON_10G */
+};
+
+/* network interface mapping table size */
+int g_net_inf_map_table_size[BAL_SWAPP_PORT_MAP__NUM_OF] = {
+ sizeof(net_inf_map_gpon)/sizeof(net_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON */
+ sizeof(net_inf_map_gpon)/sizeof(net_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON_V3 */
+ sizeof(net_inf_map_exp)/sizeof(net_inf_map_exp[0]), /* BAL_SWAPP_PORT_MAP_EXP */
+ sizeof(net_inf_map_exp2)/sizeof(net_inf_map_exp2[0]), /* BAL_SWAPP_PORT_MAP_EXP2 */
+ sizeof(net_inf_map_svk4)/sizeof(net_inf_map_svk4[0]), /* BAL_SWAPP_PORT_MAP_SVK4 */
+ sizeof(net_inf_map_epon_tdma_10g)/sizeof(net_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
+ sizeof(net_inf_map_epon_1g)/sizeof(net_inf_map_epon_1g[0]), /* BAL_SWAPP_PORT_MAP_EPON_1G */
+ sizeof(net_inf_map_epon_tdma_10g)/sizeof(net_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_10G */
+};
+/* pon interface mapping table size */
+int g_pon_inf_map_table_size[BAL_SWAPP_PORT_MAP__NUM_OF] = {
+ sizeof(pon_inf_map_gpon)/sizeof(pon_inf_map_gpon[0]), /* BAL_SWAPP_PORT_MAP_GPON */
+ sizeof(pon_inf_map_gpon_v3)/sizeof(pon_inf_map_gpon_v3[0]), /* BAL_SWAPP_PORT_MAP_GPON_V3 */
+ sizeof(pon_inf_map_exp)/sizeof(pon_inf_map_exp[0]), /* BAL_SWAPP_PORT_MAP_EXP */
+ sizeof(pon_inf_map_exp2)/sizeof(pon_inf_map_exp2[0]), /* BAL_SWAPP_PORT_MAP_EXP2 */
+ sizeof(pon_inf_map_svk4)/sizeof(pon_inf_map_svk4[0]), /* BAL_SWAPP_PORT_MAP_SVK4 */
+ sizeof(pon_inf_map_epon_tdma_10g)/sizeof(pon_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_TDMA */
+ sizeof(pon_inf_map_epon_1g)/sizeof(pon_inf_map_epon_1g[0]), /* BAL_SWAPP_PORT_MAP_EPON_1G */
+ sizeof(pon_inf_map_epon_tdma_10g)/sizeof(pon_inf_map_epon_tdma_10g[0]), /* BAL_SWAPP_PORT_MAP_EPON_10G */
+};
+
+/**
+ * @brief get the number of valid network interface
+ * @return num_nni number of nni interfaces
+ */
+int bal_bcm_net_inf_map_size_get()
+{
+ return g_net_inf_map_table_size[g_intf_maptable];
+};
+
+ /**
+ * @brief get the number of valid pon interface
+ * @return num_nni number of pon interfaces
+ */
+int bal_bcm_pon_inf_map_size_get()
+{
+ return g_pon_inf_map_table_size[g_intf_maptable];
+};
+
+/**
+ * @brief get KT2 PBM of a network interface from current mapping table
+ *
+ * @param net_inf_id logical nni interface number from CLI
+ *
+ * @return pbm PortBitMap that will be used in bcm api calls
+ */
+uint32_t bal_bcm_net_inf_pbm_get(uint32_t net_inf_id)
+{
+ bal_swapp_port *port = (g_net_inf_map_table[g_intf_maptable] + net_inf_id);
+ return port->pbm_id;
+};
+
+/**
+ * @brief get bal nni port number (index of the mapping table) of a physical nni interface
+ *
+ * @param nni_id physical nni interface in the switch
+ *
+ * @return index index to PortBitMap that contains the physical interface number
+ */
+int bal_bcm_net_inf_idx_get(uint32_t nni_id)
+{
+ int indx;
+ bal_swapp_port *port = g_net_inf_map_table[g_intf_maptable];
+ for( indx = 0; port->pbm_id != -1; indx++)
+ {
+ if (port->pbm_id == nni_id)
+ {
+ break;
+ }
+ port++;
+ }
+ if (port->pbm_id == -1)
+ {
+ return -1;
+ }
+ else
+ {
+ return indx;
+ }
+}
+
+/**
+ * @brief get KT2 device id of a network interface from current mapping table
+ *
+ * @param net_inf_id logical nni interface number from CLI
+ *
+ * @return pbm device number that will be used in bcm api calls
+ */
+int bal_bcm_net_inf_dev_get(uint32_t net_inf_id)
+{
+ if(net_inf_id > sizeof(g_net_inf_map_table))
+ {
+ return bal_bcm_dft_dev_get();
+ }
+ else
+ {
+ bal_swapp_port *port = (g_net_inf_map_table[g_intf_maptable] + net_inf_id);
+ return port->device_id;
+ }
+};
+
+/**
+ * @brief get KT2 PBM of a pon interface from current mapping table
+ *
+ * @param pon_inf_id logical pon interface number from CLI
+ *
+ * @return pbm PortBitMap that will be used in bcm api calls
+ */
+uint32_t bal_bcm_pon_inf_pbm_get(uint32_t pon_inf_id)
+{
+ bal_swapp_port *port = (g_pon_inf_map_table[g_intf_maptable] + pon_inf_id);
+ return port->pbm_id;
+};
+
+/**
+ * @brief get bal pon port number (index of the mapping table) of a physical pon interface
+ *
+ * @param pon_id physical pon interface in the switch
+ *
+ * @return index index to PortBitMap that contains the physical interface number
+ */
+int bal_bcm_pon_inf_idx_get(uint32_t pon_id)
+{
+ int indx;
+ bal_swapp_port *port = g_pon_inf_map_table[g_intf_maptable];
+ for( indx = 0; port->pbm_id != -1; indx++)
+ {
+ if (port->pbm_id == pon_id)
+ {
+ break;
+ }
+ port++;
+ }
+ if (port->pbm_id == -1)
+ {
+ return -1;
+ }
+ else
+ {
+ return indx;
+ }
+}
+
+/**
+ * @brief get KT2 device number of a pon interface from current mapping table
+ *
+ * @param pon_inf_id logical pon interface number from CLI
+ *
+ * @return pbm device number that will be used in bcm api calls
+ */
+int bal_bcm_pon_inf_dev_get(uint32_t pon_inf_id)
+{
+ if(pon_inf_id > sizeof(g_pon_inf_map_table))
+ {
+ return bal_bcm_dft_dev_get();
+ }
+ else
+ {
+ bal_swapp_port *port = (g_pon_inf_map_table[g_intf_maptable] + pon_inf_id);
+ return port->device_id;
+ }
+};
+
+/**
+ * @brief setting the local default device id
+ */
+void bal_bcm_dft_dev_set(uint32_t id)
+{
+ g_dft_dev_id = (int)id;
+}
+
+/**
+ * @brief getting the local default device id
+ */
+uint32_t bal_bcm_dft_dev_get()
+{
+ return g_dft_dev_id;
+}
+
+/**
+ * @brief setting the L2 table aging time (seconds)
+ */
+void bal_bcm_l2_age_time_set(uint32_t age_time)
+{
+ g_l2_age_time = age_time;
+}
+
+/**
+ * @brief getting current L2 table aging time value
+ */
+uint32_t bal_bcm_l2_age_time_get()
+{
+ return g_l2_age_time;
+}
+
+/**
+ * @brief getting the device type
+ */
+uint32_t bal_bcm_dev_type_get(uint32_t id)
+{
+ int rc;
+ bcm_info_t dev_info;
+
+ rc = bcm_info_get(id, &dev_info);
+ if (rc)
+ {
+ return 0;
+ }
+
+ return dev_info.device;
+}
+
+/**
+ * @brief getting the iwf mode of an access terminal
+ */
+uint32_t bal_bcm_iwf_mode_get()
+{
+ /* currently only support one access terminal */
+ BCM_LOG(DEBUG, log_id_sw_util, " Get iwf mode for acc_term\n");
+ return g_iwf_mode;
+}
+
+/**
+ * @brief setting the use of RPC (remote) or not (local)
+ */
+void bal_bcm_use_rpc_set(uint32_t use_rpc)
+{
+ g_use_rpc = (int)use_rpc;
+}
+
+/**
+ * @brief getting the use of RPC (remote) or not (local)
+ */
+bcmos_bool bal_bcm_use_rpc_get(void)
+{
+ if (g_use_rpc)
+ {
+ return BCMOS_TRUE;
+ }
+ else
+ {
+ return BCMOS_FALSE;
+ }
+}
+
+static void sw_util_bcm_rx_cb (int unit, int port, int reason, unsigned char *p_payload, int payload_len)
+{
+ int i, len, obj_len;
+ unsigned char *payload;
+ char bytestr[32];
+ char *p_bytestr = bytestr;
+
+ BCM_LOG(INFO, log_id_sw_util, "BAL: Captured packet from datapath (len: %d bytes)\n", payload_len);
+
+ BCM_LOG(DEBUG, log_id_sw_util, " ingress port %d\n", port);
+ BCM_LOG(DEBUG, log_id_sw_util, " rcv reason 0x%x\n", reason);
+
+ len = (payload_len > 64)? 64 : payload_len;
+
+ /* dump out the captured packet */
+ payload = p_payload;
+ BCM_LOG(DEBUG, log_id_sw_util, " payload: (first %d bytes shown)", len);
+ for(i=0; i<len; i++)
+ {
+ if ( i%8 == 0)
+ {
+ sprintf(p_bytestr, "\n");
+ BCM_LOG(DEBUG, log_id_sw_util, "%s", bytestr);
+ p_bytestr = bytestr;
+
+ }
+ sprintf(p_bytestr, " %02x", *payload++);
+ p_bytestr += 3;
+ }
+
+ /* Log the string being crafted when the loop terminated */
+ sprintf(p_bytestr, "\n");
+ BCM_LOG(DEBUG, log_id_sw_util, "%s", bytestr);
+
+ /* Send Auto Indication */
+ if ( p_bal_core_to_api_ind_queue )
+ {
+ bcmbal_packet_cfg *p_ind_msg = NULL;
+ bcmbal_packet_key key;
+ bal_sw_flow *p_flow_elm;
+ int tmp_port;
+
+ /* find the flow info corresponding to this trap REASON */
+ p_flow_elm = bal_sw_util_flow_list_get_by_trap_code(reason);
+ if(p_flow_elm == NULL)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " TrapCallBack: Can't match trap code 0x%x to element in flow list\n", reason);
+ return;
+ }
+
+ /* The packet indication object contains the bcmbal_packet_cfg structure plus the captured packet
+ * content
+ */
+ obj_len = payload_len + sizeof(bcmbal_packet_cfg);
+
+ p_ind_msg = bcmbal_msg_calloc(obj_len);
+
+ if(p_ind_msg == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: No memory to send indication\n");
+ return;
+ }
+
+ key.packet_send_dest.type = BCMBAL_DEST_TYPE_HOST;
+
+ BCMBAL_CFG_INIT(p_ind_msg, packet, key);
+
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_id, p_flow_elm->id);
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, svc_port, p_flow_elm->svc_port);
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_cookie, p_flow_elm->flow_cookie);
+
+ /* first search the PON table */
+ tmp_port = bal_bcm_pon_inf_idx_get(port);
+ if( tmp_port != -1)
+ {
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_type, BCMBAL_FLOW_TYPE_UPSTREAM);
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_id, tmp_port);
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_type, BCMBAL_INTF_TYPE_PON);
+ }
+ else /* if failed, search for NNI table */
+ {
+ tmp_port = bal_bcm_net_inf_idx_get(port);
+ if( tmp_port != -1)
+ {
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, flow_type, BCMBAL_FLOW_TYPE_DOWNSTREAM);
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_id, tmp_port);
+ BCMBAL_CFG_PROP_SET(p_ind_msg, packet, intf_type, BCMBAL_INTF_TYPE_NNI);
+ }
+ }
+ /* if both failed, return */
+ if(tmp_port == -1)
+ {
+ /* something went wrong, free up the message */
+ bcmbal_msg_free(p_ind_msg);
+ BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: can't match ingress port to bal port tables\n");
+ return;
+ }
+
+ ((bcmbal_obj *)p_ind_msg)->status = BCM_ERR_OK;
+ ((bcmbal_obj *)p_ind_msg)->obj_type = BCMBAL_OBJ_ID_PACKET;
+ ((bcmbal_obj *)p_ind_msg)->group = BCMBAL_MGT_GROUP_AUTO;
+
+ /* now copy the contents of the packet */
+ p_ind_msg->data.pkt.val = (uint8_t *)(p_ind_msg + 1);
+ memcpy(p_ind_msg->data.pkt.val, p_payload, payload_len);
+
+ /* and record the length of the captured packet */
+ p_ind_msg->data.pkt.len = payload_len;
+
+ BCMBAL_PROP_SET_PRESENT(p_ind_msg, packet, _cfg, pkt);
+
+ BCM_LOG(INFO, log_id_sw_util, " TrapCallBack: Flow id = %d, type=%d, Interface id = %d, type=%d, svc_port=%d\n",
+ p_ind_msg->data.flow_id, p_ind_msg->data.flow_type,
+ p_ind_msg->data.intf_id, p_ind_msg->data.intf_type,
+ p_ind_msg->data.svc_port);
+
+ /* Send this indication straight to the API client
+ */
+ bcmbal_msg_hdr_set(p_ind_msg,
+ BCMBAL_MGMT_API_IND_MSG,
+ BAL_MSG_TYPE_AUTO_IND,
+ BAL_SUBSYSTEM_CORE,
+ BCMBAL_OBJ_ID_PACKET,
+ 0, /* operation code */
+ 0); /* exchange id */
+
+ if(BCM_ERR_OK != bcmbal_msg_send(p_bal_core_to_api_ind_queue,
+ p_ind_msg,
+ BCMOS_MSG_SEND_AUTO_FREE))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: send auto indication failed\n");
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " TrapCallBack: auto indication sent\n");
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " TrapCallBack: no auto indication queue\n");
+ }
+ return;
+}
+
+/**
+ * @brief Connect access terminal
+ *
+ * This routine is called by acc_term_fsm in the BAL core
+ * Upon receiving the request from the core, this function
+ * assign the device number that each logical nni or pon interface belong
+ * and restrict the egress ports of each interface. This mapping is highly
+ * topology dependent and should be customized according to the actual hardware
+ * layout.
+ * @param p_acc_term Pointer to access terminal instance
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno sw_util_access_terminal_connect(acc_term_inst *p_acc_term)
+{
+ bcmos_errno ret = BCM_ERR_INTERNAL;
+ int rc;
+ bal_swapp_port *port;
+ char *argv[] = { "socdiag", NULL };
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util, " Got a access terminal SET\n");
+
+ /* make sure the abstraction layer is initialized - no harm to initialize multiple time */
+ bcmos_init();
+
+ /* Initialize SDK */
+ rc = socdiag_main(1, argv);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Init BCM SDK failed - %d\n", rc);
+ return BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " %s RPC\n", (1 == g_use_rpc) ? "Using" : "Not using" );
+
+ /* use a soc script to establish rpc connection if switch is remotely located */
+ if (bal_bcm_use_rpc_get())
+ {
+ sleep(3); /* allow remote device to settle */
+
+ BCM_LOG(INFO, log_id_sw_util, " starting RPC connection\n");
+ rc = sh_rcload_file(-1, NULL, "rpc.soc", 0);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " start RPC connection failed\n");
+ return BCM_ERR_INTERNAL;
+ }
+
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Using interface table: %d Device: %d\n", g_intf_maptable, g_dft_dev_id );
+
+ /* setup the device ID - This is very hardware specific */
+ port = g_net_inf_map_table[g_intf_maptable];
+ /* -1 indicate end of table */
+ while(port->pbm_id != -1)
+ {
+ port->device_id = g_dft_dev_id;
+ port++;
+ }
+
+ port = g_pon_inf_map_table[g_intf_maptable];
+ while(port->pbm_id != -1)
+ {
+ port->device_id = g_dft_dev_id;
+ port++;
+ }
+ /* get the switch model from the chip */
+ dev_type = bal_bcm_dev_type_get(g_dft_dev_id);
+ if (dev_type == 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Error retrieving device type on access-terminal connect: 0x%x\n", dev_type);
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* set up the valid egress ports for net/pon facing ports */
+ if (dev_type == BCM_DEVICE_KT2)
+ {
+ ret = sw_util_esw_acc_term_connect(g_net_inf_map_table[g_intf_maptable], g_pon_inf_map_table[g_intf_maptable]);
+ }
+ else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ /* for rpc case, dpp use a special api to register rx callback.
+ for non-rpc use case, use bcm_rx_register() to register the rx callback
+ */
+ if (bal_bcm_use_rpc_get())
+ {
+ /* if the trap receive udp port in bal_config.ini is not zero, start a receiving thread */
+ if(bal_bcm_trap_rcv_port_get())
+ {
+ sw_util_dpp_rx_cb_register(bal_bcm_dft_dev_get(), sw_util_bcm_rx_cb);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Missing UDP port number for RPC packet In receiver \n");
+ return BCM_ERR_INTERNAL;
+ }
+ }
+ else
+ {
+ bcm_rx_register(bal_bcm_dft_dev_get(), "Bal Cpu Traps", dpp_rx_cb_register, 50, NULL, BCM_RCO_F_ALL_COS);
+ }
+
+ ret = sw_util_dpp_acc_term_connect(g_net_inf_map_table[g_intf_maptable], g_pon_inf_map_table[g_intf_maptable]);
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return access terminal connect request with %d on device 0x%x\n", ret, dev_type );
+
+ /* for now, only support one iwf */
+ g_iwf_mode = (uint32_t)p_acc_term->api_req_acc_term_obj_info.data.iwf_mode;
+
+ return ret;
+}
+
+/**
+ * @brief getting the interface mapping table that applied to the HW connections
+ */
+bal_swapp_port_map_indx bal_bcm_intf_maptable_get()
+{
+ return g_intf_maptable;
+}
+
+/**
+ * @brief SWITCH module: internal packet_send function
+ *
+ * This routine distribute the SEND function to supported switch family
+ *
+ * @param dst_port_id Switch port id the packet is going to be sent out
+ * @param reason REASON_SEND_TO_NNI or REASON_SEND_TO_PON
+ * @param payload pointer to the data
+ * @param payload_len the length of the data
+ * @param tunnel_id pon port tunnel id if REASON_SEND_TO_PON
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno sw_util_pkt_send_intl(int dst_port_id,
+ int reason,
+ unsigned char *payload,
+ int payload_len,
+ int tunnel_id)
+{
+ uint32_t dev_type;
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /* get the switch chip type from default device id
+ TBD - in the future, the device id should be obtained from port mapping table */
+ dev_type = bal_bcm_dev_type_get(g_dft_dev_id);
+ if (dev_type == 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Error retrieving device type on pkt send: 0x%x\n", dev_type);
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* set up the valid egress ports for net/pon facing ports */
+ if (dev_type == BCM_DEVICE_KT2)
+ {
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = sw_util_dpp_pkt_send(dst_port_id, reason, payload, payload_len, s_target_device, tunnel_id);
+ }
+ else
+ {
+ ret = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return access terminal connect request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+
+/* the listening UDP port that the switch will send the trapped messages */
+static uint32_t g_trap_rcv_port = 0;
+
+/**
+ * @brief set the receiving UDP port for trap packets - from config file
+ */
+uint32_t bal_bcm_trap_rcv_port_set(uint32_t udp_port)
+{
+ g_trap_rcv_port = udp_port;
+ return 0;
+}
+
+/**
+ * @brief getting the receiving UDP port for trap packets
+ */
+uint32_t bal_bcm_trap_rcv_port_get()
+{
+ return g_trap_rcv_port;
+}
+
+
+/* the global portChannel DownStream Max rate scheduling mode */
+static uint32_t g_ds_sched_mode = 0; /* default to strict priority */
+
+/**
+ * @brief set the DS max rate scheduling mode - from config file
+ */
+uint32_t bal_bcm_ds_sched_mode_set(uint32_t sched_mode)
+{
+ g_ds_sched_mode = sched_mode;
+ return 0;
+}
+
+/**
+ * @brief getting the DS max rate scheduling mode
+ */
+uint32_t bal_bcm_ds_sched_mode_get()
+{
+ return g_ds_sched_mode;
+}
+
+/**
+ * @brief SWITCH module: access terminal SET handler
+ *
+ * This routine is called by acc_term_fsm in the BAL core upon
+ * SET request for acc_terminal object.
+ *
+ * @param p_acc_term Pointer to access terminal instance
+ * @param opt_type Operation type on access terminal instance
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_access_terminal_set(acc_term_inst *p_acc_term,
+ bal_util_oper_acc_term opt_type)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ if (opt_type != BAL_UTIL_OPER_ACC_TERM_CONNECT)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Access terminal currently supports only CONNECT request\n");
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ ret = sw_util_access_terminal_connect(p_acc_term);
+#else
+ BCM_LOG(INFO, log_id_sw_util, " dummy SUCCESS\n");
+#endif
+
+ return ret;
+}
+
+/**
+ * @brief setting the interface mapping table that applied to the HW connections
+ */
+int bal_bcm_intf_maptable_set(uint32_t intf_maptable)
+{
+ int ret = 0;
+#ifndef TEST_SW_UTIL_LOOPBACK
+ switch(intf_maptable)
+ {
+ case 0:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON;
+ break;
+ case 1:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_GPON_V3;
+ break;
+ case 2:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_EXP;
+ break;
+ case 3:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_EXP2;
+ break;
+ case 4:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_SVK4;
+ break;
+ case 5:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_TDMA;
+ break;
+ case 6:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_1G;
+ break;
+ case 7:
+ g_intf_maptable = BAL_SWAPP_PORT_MAP_EPON_10G;
+ break;
+ default:
+ BCM_LOG(ERROR, log_id_sw_util, " Mapping Table Id %d is not supported\n", intf_maptable);
+ ret = BCM_ERR_NOT_SUPPORTED;
+ break;
+ }
+#endif
+ return ret;
+}
+
+/**
+ * @brief SWITCH module: packet_send
+ *
+ * This routine is called by work thread in the BAL core upon
+ * user request to send a raw packet out of a switch port.
+ *
+ * @param dst_port_id Switch port id the packet is going to be sent out
+ * @param reason REASON_SEND_TO_NNI or REASON_SEND_TO_PON
+ * @param payload pointer to the data
+ * @param payload_len the length of the data
+ * @param tunnel_id pon tunnel_id
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_pkt_send(int dst_port_id,
+ int reason,
+ unsigned char *payload,
+ int payload_len,
+ int tunnel_id)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ if ( reason != REASON_SEND_TO_NNI && reason != REASON_SEND_TO_PON)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " pkt_send currently does not support reason %d\n", reason);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if ( reason == REASON_SEND_TO_NNI && BCMOS_FALSE == bcm_topo_nni_is_valid(dst_port_id))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " pkt_send to invalid nni port %d\n", dst_port_id);
+ return BCM_ERR_PARM;
+ }
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ ret = sw_util_pkt_send_intl(dst_port_id, reason, payload, payload_len, tunnel_id);
+#else
+ BCM_LOG(INFO, log_id_sw_util, " dummy SUCCESS\n");
+#endif
+
+ return ret;
+}
+
+/*
+ * Called from bal_core to set up the packet out server IP:port (i.e. the bcm_user process location)
+ * when Switch is on the same board where the core is run, there is no RPC and this init function should not be called
+ */
+bcmos_errno sw_util_pkt_send_init(const char *pkt_send_server_ip, uint16_t pkt_send_server_listen_port)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+ do
+ {
+ /* If the packet_out interface has already been initialized, just return OK */
+ if(g_pkt_send_is_initialized == BCMOS_FALSE)
+ {
+#ifdef CONFIG_SWITCH_RPC
+ /*
+ * Set up the socket to be used for sending "packet send" messages
+ * to the bcm.user server
+ */
+ if((s_target_device.socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ {
+ ret = BCM_ERR_NORES;
+ break;
+ }
+
+ s_target_device.addr.sin_family = AF_INET;
+ inet_pton(s_target_device.addr.sin_family, pkt_send_server_ip, &s_target_device.addr.sin_addr.s_addr);
+ s_target_device.addr.sin_port = htons(pkt_send_server_listen_port);
+#endif /* CONFIG_SWITCH_RPC */
+ g_pkt_send_is_initialized = BCMOS_TRUE;
+ }
+
+ }
+ while(0);
+
+#endif /*TEST_SW_UTIL_LOOPBACK*/
+
+ return ret;
+}
+/*@}*/
diff --git a/bal_release/src/core/util/switch/bal_switch_acc_term.h b/bal_release/src/core/util/switch/bal_switch_acc_term.h
new file mode 100644
index 0000000..e60b91b
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_acc_term.h
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_acc_term.h
+ *
+ * @brief bal switch util access terminal service function header file
+ *
+ * @addtogroup sw_util
+ */
+
+#ifndef _BAL_BCM_ACC_TERM_H_
+#define _BAL_BCM_ACC_TERM_H_
+
+/*@{*/
+#include "bcmos_errno.h"
+
+#define BAL_BCM_MAX_INTF 32
+
+/* structure of each entry in the port mapping table */
+typedef struct bal_swapp_port_t
+{
+ uint32_t pbm_id;
+ int device_id;
+} bal_swapp_port;
+
+/* Index of different tables that map core interface number to physical ports on the device
+ * for example, GPON mapping table will be table[0], EPON mapping table will be table[2]
+ */
+typedef enum
+{
+ BAL_SWAPP_PORT_MAP_GPON,
+ BAL_SWAPP_PORT_MAP_GPON_V3,
+ BAL_SWAPP_PORT_MAP_EXP,
+ BAL_SWAPP_PORT_MAP_EXP2,
+ BAL_SWAPP_PORT_MAP_SVK4,
+ BAL_SWAPP_PORT_MAP_EPON_TDMA,
+ BAL_SWAPP_PORT_MAP_EPON_1G,
+ BAL_SWAPP_PORT_MAP_EPON_10G,
+ BAL_SWAPP_PORT_MAP__NUM_OF,
+} bal_swapp_port_map_indx;
+
+/*
+ * @brief Packet send structures and defines
+ */
+enum
+{
+ REASON_SEND_TO_NNI = 1,
+ REASON_SEND_TO_PON
+};
+
+typedef struct
+{
+ int socket;
+ struct sockaddr_in addr;
+} trap_target;
+
+extern bcmos_errno bal_bcm_acc_term_connect(void);
+extern void bal_bcm_dft_dev_set(uint32_t id);
+extern uint32_t bal_bcm_dft_dev_get(void);
+extern void bal_bcm_l2_age_time_set(uint32_t time);
+extern uint32_t bal_bcm_l2_age_time_get(void);
+extern uint32_t bal_bcm_dev_type_get(uint32_t id);
+extern void bal_bcm_use_rpc_set(uint32_t use_rpc);
+extern int bal_bcm_intf_maptable_set(uint32_t intf_maptable);
+extern uint32_t bal_bcm_net_inf_pbm_get(uint32_t net_inf_id);
+extern uint32_t bal_bcm_pon_inf_pbm_get(uint32_t pon_inf_id);
+extern int bal_bcm_net_inf_dev_get(uint32_t net_inf_id);
+extern int bal_bcm_pon_inf_dev_get(uint32_t pon_inf_id);
+extern uint32_t bal_bcm_iwf_mode_get(void);
+extern bcmos_bool bal_bcm_use_rpc_get(void);
+extern uint32_t bal_bcm_trap_rcv_port_get(void);
+extern uint32_t bal_bcm_trap_rcv_port_set(uint32_t udp_port);
+extern int bal_bcm_pon_inf_idx_get(uint32_t pon_id);
+extern int bal_bcm_net_inf_idx_get(uint32_t nni_id);
+extern bal_swapp_port_map_indx bal_bcm_intf_maptable_get(void);
+extern uint32_t bal_bcm_ds_sched_mode_get(void);
+extern uint32_t bal_bcm_ds_sched_mode_set(uint32_t sched_mode);
+extern bcmos_errno sw_util_pkt_send(int dst_port_id, int reason, unsigned char *payload, int payload_len, int tunnel_id);
+extern bcmos_errno sw_util_pkt_send_init(const char *pkt_send_server_ip, uint16_t pkt_send_server_listen_port);
+extern int bal_bcm_net_inf_map_size_get(void);
+extern int bal_bcm_pon_inf_map_size_get(void);
+/*@}*/
+
+#endif
diff --git a/bal_release/src/core/util/switch/bal_switch_cli.c b/bal_release/src/core/util/switch/bal_switch_cli.c
new file mode 100644
index 0000000..779f125
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_cli.c
@@ -0,0 +1,172 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_cli.c
+ * @brief Sample CLI for switch integration module
+ *
+ */
+
+/*@{*/
+
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_util.h"
+#include <bcmcli.h>
+
+/* Below local functions are used for real logic only */
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+#include "bal_switch_acc_term.h"
+#include <bcm/types.h>
+#include <bcm/port.h>
+#include <appl/diag/shell.h>
+
+static bcmcli_entry *switch_cli_dir;
+
+/* Function declarations */
+
+/*
+ * CLI backend helper functions
+ */
+
+static bcmos_errno bal_switch_device(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bal_bcm_dft_dev_set(parm[0].value.number);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_switch_l2_age_time(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bal_bcm_l2_age_time_set(parm[0].value.number);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_switch_rpc_mode(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bal_bcm_use_rpc_set(parm[0].value.number);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_switch_intf_map(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bal_bcm_intf_maptable_set(parm[0].value.number);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_switch_trap_udp_port(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ bal_bcm_trap_rcv_port_set(parm[0].value.number);
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bal_switch_shell(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ sh_process(-1, "BCM", TRUE);
+ return BCM_ERR_OK;
+}
+/* allow CLI to send a testing packet out of NNI interface, input is interface_number */
+static bcmos_errno bal_switch_pkt_out(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ int out_port = parm[0].value.number;
+ unsigned char pkt_tagged_data[64] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* DA */
+ 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, /* SA */
+ 0x81, 0x00, 0x00, 0x01, /* TPID + VID */
+ 0x08, 0x00, 0x45, 0x10, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x32, 0x06,
+ 0x82, 0xab, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
+ 0x03, 0x04, 0x00, 0x04, 0x01, 0x00, 0x56, 0xf1, 0x39, 0x00, 0x00,
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
+ sw_util_pkt_send(out_port, REASON_SEND_TO_NNI, pkt_tagged_data, 64, 0);
+ return BCM_ERR_OK;
+}
+
+/* allow CLI to send a testing packet out of PON interface, inputs are interface_number and tunnel_id */
+static bcmos_errno bal_switch_pon_out(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms)
+{
+ int out_port = parm[0].value.number;
+ int tunnel_id = parm[1].value.number;
+ unsigned char pkt_tagged_data[64] = {
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, /* DA */
+ 0x00, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, /* SA */
+ 0x81, 0x00, 0x00, 0x01, /* TPID + VID */
+ 0x08, 0x00, 0x45, 0x10, 0x00, 0x46, 0x00, 0x00, 0x00, 0x00, 0x32, 0x06,
+ 0x82, 0xab, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02,
+ 0x03, 0x04, 0x00, 0x04, 0x01, 0x00, 0x56, 0xf1, 0x39, 0x00, 0x00,
+ 0x11, 0x22, 0x33, 0x44, 0x55, 0x66};
+
+ sw_util_pkt_send(out_port, REASON_SEND_TO_PON, pkt_tagged_data, 64, tunnel_id);
+ return BCM_ERR_OK;
+}
+
+#endif
+
+/* Create CLI directory */
+bcmos_errno sw_util_cli_init(bcmcli_entry *top_dir)
+{
+#ifndef TEST_SW_UTIL_LOOPBACK
+ if (switch_cli_dir)
+ {
+ return BCM_ERR_ALREADY;
+ }
+ switch_cli_dir = bcmcli_dir_add(top_dir, "switch", "Switch CLI commands", BCMCLI_ACCESS_GUEST, NULL);
+ BCMOS_CHECK_RETURN_ERROR(!switch_cli_dir, BCM_ERR_INTERNAL);
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "device", "Set default device", bal_switch_device,
+ BCMCLI_MAKE_PARM("index", "Device index", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "l2_agetime", "Set L2 table aging time", bal_switch_l2_age_time,
+ BCMCLI_MAKE_PARM("time", "L2 Aging Time", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "rpc_mode", "Set RPC mode", bal_switch_rpc_mode,
+ BCMCLI_MAKE_PARM_ENUM("enable", "Enable RPC mode", bcmcli_enum_bool_table, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "intf_map_table", "Select interface mapping table", bal_switch_intf_map,
+ BCMCLI_MAKE_PARM("table", "Interface Mapping Table Number", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "trap_udp_port", "Set trap packet receiving udp port", bal_switch_trap_udp_port,
+ BCMCLI_MAKE_PARM("port", "Receiving Port number", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "nni_packet_out", "Send example packet vid=1 to switch nni port", bal_switch_pkt_out,
+ BCMCLI_MAKE_PARM("port", "Sending Port number", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD(switch_cli_dir, "pon_packet_out", "Send example packet vid=1 to switch pon port", bal_switch_pon_out,
+ BCMCLI_MAKE_PARM("port", "Sending Port number", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE),
+ BCMCLI_MAKE_PARM("tunnel", "Sending Tunnel Id", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_NONE));
+
+ BCMCLI_MAKE_CMD_NOPARM(switch_cli_dir, "shell", "Switch SDK shell", bal_switch_shell);
+#endif
+ return BCM_ERR_OK;
+}
+
+/*@}*/
diff --git a/bal_release/src/core/util/switch/bal_switch_flow.c b/bal_release/src/core/util/switch/bal_switch_flow.c
new file mode 100644
index 0000000..acb85d3
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_flow.c
@@ -0,0 +1,664 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_flow.c
+ * @brief BAL Switch util functions that handle flow requests
+ * @addtogroup sw_util
+ */
+
+ /*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_flow.h"
+#include "flow_fsm.h"
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <bcm/types.h>
+#include <sal/core/libc.h>
+#ifndef sal_memset
+#define sal_memset memset
+#endif
+#include <bcm/port.h>
+#include <bcm/vlan.h>
+#include <bcm/field.h>
+#include <bcm/error.h>
+#include <sal/core/libc.h>
+
+#include "bal_switch_acc_term.h"
+#include "esw/bal_esw_flow.h"
+#include "dpp/bal_dpp_flow.h"
+#include "dpp/bal_dpp_vswitch.h"
+
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+
+/* A golbal link list to keep track of flows in the switch */
+TAILQ_HEAD(bal_sw_flow_list_head, bal_sw_flow) g_swutil_flow_list;
+
+static void sw_util_flow_dump_classifier(bcmbal_flow_cfg *p_flow)
+{
+ char dst_ip_str[16];
+
+ bcmos_inet_ntoa(&p_flow->data.classifier.dst_ip, dst_ip_str);
+
+ /* Do not use normal BCM_LOG() (but BCM_LOG_CALLER_FMT()), as IP address is a stack variable. */
+ BCM_LOG_CALLER_FMT(DEBUG, log_id_sw_util,
+ " classifier - otpid=0x%x itpid=0x%x ovid=0x%x ivid=0x%x opcp=0x%x, ipcp=0x%x "
+ "ether_type=0x%x dst_mac=%02x:%02x:%02x:%02x:%02x:%02x ip_proto=0x%x dst_ip=%s src_port=%u dst_port=%u attr_mask=0x%x\n",
+ p_flow->data.classifier.o_tpid, p_flow->data.classifier.i_tpid,
+ p_flow->data.classifier.o_vid, p_flow->data.classifier.i_vid,
+ p_flow->data.classifier.o_pbits,
+ p_flow->data.classifier.i_pbits,
+ p_flow->data.classifier.ether_type,
+ p_flow->data.classifier.dst_mac.u8[0], p_flow->data.classifier.dst_mac.u8[1], p_flow->data.classifier.dst_mac.u8[2],
+ p_flow->data.classifier.dst_mac.u8[3], p_flow->data.classifier.dst_mac.u8[4], p_flow->data.classifier.dst_mac.u8[5],
+ p_flow->data.classifier.ip_proto,
+ dst_ip_str,
+ p_flow->data.classifier.src_port,
+ p_flow->data.classifier.dst_port,
+ (unsigned int)p_flow->data.classifier.presence_mask);
+}
+
+static void sw_util_flow_dump_sla(bcmbal_flow_cfg *p_flow)
+{
+ BCM_LOG(DEBUG, log_id_sw_util, " sla - min_rate=%u max_rate=%u attr_mask=0x%x\n",
+ p_flow->data.sla.min_rate,
+ p_flow->data.sla.max_rate,
+ (unsigned int)p_flow->data.sla.presence_mask);
+}
+
+#define OUTER_VLAN_TAG_REQ_BITMASK (BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG | \
+ BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG | \
+ BCMBAL_ACTION_CMD_ID_XLATE_TWO_TAGS | \
+ BCMBAL_ACTION_CMD_ID_REMOVE_TWO_TAGS | \
+ BCMBAL_ACTION_CMD_ID_REMARK_PBITS | \
+ BCMBAL_ACTION_CMD_ID_COPY_PBITS | \
+ BCMBAL_ACTION_CMD_ID_REVERSE_COPY_PBITS | \
+ BCMBAL_ACTION_CMD_ID_DSCP_TO_PBITS)
+
+#define NOT_WORKING_ACTION_BITMASK (BCMBAL_ACTION_CMD_ID_ADD_TWO_TAGS | \
+ BCMBAL_ACTION_CMD_ID_REMOVE_TWO_TAGS | \
+ BCMBAL_ACTION_CMD_ID_XLATE_TWO_TAGS | \
+ BCMBAL_ACTION_CMD_ID_DISCARD_DS_BCAST | \
+ BCMBAL_ACTION_CMD_ID_DISCARD_DS_UNKNOWN | \
+ BCMBAL_ACTION_CMD_ID_COPY_PBITS | \
+ BCMBAL_ACTION_CMD_ID_REVERSE_COPY_PBITS | \
+ BCMBAL_ACTION_CMD_ID_DSCP_TO_PBITS)
+
+/**
+ * @brief The flow check function validate the flow parameters from the core
+ *
+ * @param p_msg A pointer to the flow object to validate
+ * @return error code
+ */
+bcmos_errno sw_util_flow_info_validate(void *p_msg)
+{
+ bcmbal_flow_cfg *p_flow = (bcmbal_flow_cfg *)p_msg;
+ bcmos_errno ret = BCM_ERR_OK;
+
+ if (p_flow == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " No flow specified during validation\n" );
+ return BCM_ERR_PARM;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a flow request - flow_id=%d sub_port=%d svc_id=%d, attr_mask=0x%x\n",
+ p_flow->key.flow_id, p_flow->data.access_int_id,
+ p_flow->data.svc_port_id, (unsigned int)p_flow->hdr.hdr.presence_mask);
+
+ sw_util_flow_dump_classifier(p_flow);
+ if (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM)
+ sw_util_flow_dump_sla(p_flow);
+ }
+
+ /* validate the NNI range */
+ if((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id)) &&
+ (BCMOS_FALSE == bcm_topo_nni_is_valid(p_flow->data.network_int_id )) )
+ {
+ uint32_t max_nni_ports = 0;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ bcm_topo_dev_get_max_nni(bal_bcm_net_inf_dev_get(p_flow->data.network_int_id), &max_nni_ports);
+#else
+ bcm_topo_dev_get_max_nni(0, &max_nni_ports);
+#endif
+ BCM_LOG(ERROR, log_id_sw_util,
+ " Request network interface %d is out of max range %d\n",p_flow->data.network_int_id, max_nni_ports );
+ return BCM_ERR_PARM;
+ }
+
+ /* return BCM_ERR_NOT_SUPPORTED for actions that has not yet implemented */
+ if((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
+ (p_flow->data.action.cmds_bitmask & NOT_WORKING_ACTION_BITMASK))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " Request Action Command 0x%x not supported yet\n",p_flow->data.action.cmds_bitmask );
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, classifier))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " a classifier must be specified in a flow\n" );
+ ret = BCM_ERR_PARM;
+ }
+ else
+ {
+ /* ING SDK allows priority range from 0x7fffffff to 0 */
+ /* Need to check the configuration range if unit32_t is used for the attribute */
+
+ /* An outer vid is required in the classifier for all actions that operate on the outer vlan tag */
+ if(BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid) &&
+ ((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
+ (p_flow->data.action.cmds_bitmask & OUTER_VLAN_TAG_REQ_BITMASK)))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " o_vid must be specified when actions requiring an outer vlan tag is specified\n" );
+ ret = BCM_ERR_PARM;
+ }
+
+ /*An outer vid must be specified when an inner vid is specified */
+ if((BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid)) &&
+ (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid)))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " o_vid must be specified when i_vid is specified\n" );
+ ret = BCM_ERR_PARM;
+ }
+
+ /* Check that user has specified pbits when the action is pbit remarking */
+ if((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
+ (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_REMARK_PBITS) )
+ {
+ if((BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid)) ||
+ (BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.action, action, o_pbits)) )
+ {
+
+ BCM_LOG(ERROR, log_id_sw_util,
+ " o_vid in classifier and o_pibts in action must be specified when outer pbit remarking is specified\n" );
+ ret = BCM_ERR_PARM;
+ }
+ }
+
+ /* Check that the user has specified a valid packet tag type given the o_vid and i_vid choices (if any)*/
+ if(((BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid)) ||
+ (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid))))
+ {
+ if((BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type)) ||
+ ((BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type)) &&
+ (BCMBAL_PKT_TAG_TYPE_UNTAGGED == p_flow->data.classifier.pkt_tag_type)))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " pkt_tag_type must be either SINGLE or DOUBLE tagged when o_vid or i_vid are specified\n" );
+ ret = BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ /* If the pkt_tag_type is not specified OR the pkt_tag_type is not UNTAGGED (and it's not destined
+ * to the host CPU), then it's an error
+ */
+ if(!(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action) &&
+ (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)))
+ {
+ if(BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type) ||
+ (!(BCMBAL_PKT_TAG_TYPE_UNTAGGED == p_flow->data.classifier.pkt_tag_type)))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " pkt_tag_type must be UNTAGGED when neither o_vid nor i_vid are specified\n" );
+ ret = BCM_ERR_PARM;
+ }
+ }
+ }
+
+ /* Now test the multicast flow cases */
+ if (BCMOS_TRUE == (BCMBAL_FLOW_TYPE_MULTICAST == p_flow->key.flow_type))
+ {
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action) &&
+ (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " A multicast flow must not terminate in the host\n");
+ ret = BCM_ERR_PARM;
+ }
+
+ /* A Multicast flow must have a group_id that is valid (i.e. an active group) */
+ if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " A multicast flow must have a specified group_id\n");
+ ret = BCM_ERR_PARM;
+ }
+ else
+ {
+ /* Now check that the referenced group is valid */
+ bcmbal_group_key group_key = { .group_id = p_flow->data.group_id };
+ bcmbal_group_owner group_owner;
+
+ /* make sure the group owner is multicast */
+ if(BCM_ERR_OK == group_owner_get(group_key, &group_owner))
+ {
+ if ( BCMBAL_GROUP_OWNER_MULTICAST != group_owner)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " A multicast flow must have group owner of type Multicast, group_id:%d\n",
+ group_key.group_id);
+ ret = BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " A multicast flow must have an valid group_id (Active group_id:%d not found)\n",
+ group_key.group_id);
+ ret = BCM_ERR_PARM;
+ }
+ }
+ }
+ /* check N:1 service Group Owner to be UNICAST */
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id) &&
+ (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow->key.flow_type ||
+ BCMBAL_FLOW_TYPE_UPSTREAM == p_flow->key.flow_type )
+ )
+ {
+ /* Now check that the referenced group is valid */
+ bcmbal_group_key group_key = { .group_id = p_flow->data.group_id };
+ bcmbal_group_owner group_owner;
+
+ /* make sure the group owner is unicast */
+ if(BCM_ERR_OK == group_owner_get(group_key, &group_owner))
+ {
+ if ( BCMBAL_GROUP_OWNER_UNICAST != group_owner)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " A N:1 flow must have group owner of type unicast, group_id:%d\n",
+ group_key.group_id);
+ ret = BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " A N:1 flow must have an valid group_id (Active group_id:%d not found)\n",
+ group_key.group_id);
+ ret = BCM_ERR_PARM;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/* Below local functions are used for real logic only */
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+/**
+ * @brief The flow add function program the switch to forward packets that have
+ * specified attributes to the designated ports.
+ * The packets is modified before egress
+ * On the downstream, an access id (outer vlan tag) is added to the packets
+ * On the upstream, outer vlan tag (access id) is removed from the packets
+ *
+ * @param p_flow_inst A pointer to the flow instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_flow_add(flow_inst *p_flow_inst)
+{
+ bcmbal_flow_cfg *p_flow = &p_flow_inst->api_req_flow_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+ bcmbal_iwf_mode iwf_mode;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a flow request - flow_id=%d sub_port=%d svc_id=%d\n",
+ p_flow->key.flow_id, p_flow->data.access_int_id, p_flow->data.svc_port_id);
+
+ unit = bal_bcm_pon_inf_dev_get(p_flow->data.access_int_id);
+ dev_type = bal_bcm_dev_type_get(unit);
+ iwf_mode = bal_bcm_iwf_mode_get();
+
+ /* call the flow add function based on device type */
+ if (dev_type == BCM_DEVICE_KT2)
+ {
+ ret = bal_sw_util_esw_flow_add(iwf_mode, p_flow);
+ }
+ else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_flow_add(iwf_mode, p_flow);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on flow add: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return flow add request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+
+/**
+ * @brief The flow remove function program switch to release resource that have
+ * been allocated during the flow add operation.
+ *
+ * @param p_flow_inst A pointer to the flow instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_flow_remove(flow_inst *p_flow_inst)
+{
+ bcmbal_flow_cfg *p_flow = &p_flow_inst->api_req_flow_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+ bcmbal_iwf_mode iwf_mode;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a flow remove request - flow_id=%d sub_port=%d svc_id=%d\n",
+ p_flow->key.flow_id, p_flow->data.access_int_id, p_flow->data.svc_port_id);
+
+ unit = bal_bcm_pon_inf_dev_get(p_flow->data.access_int_id);
+ dev_type = bal_bcm_dev_type_get(unit);
+ iwf_mode = bal_bcm_iwf_mode_get();
+
+ /* call the flow add function based on device type */
+ if (dev_type == BCM_DEVICE_KT2)
+ {
+ ret = bal_sw_util_esw_flow_remove(iwf_mode, p_flow);
+ }
+ else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_flow_remove(iwf_mode, p_flow);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on flow remove: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return flow remove request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+
+/**
+ * @brief The flow list init function prepare a link list to keep track of flows in the switch util
+ *
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_flow_list_init(void)
+{
+ TAILQ_INIT(&g_swutil_flow_list);
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The flow list finish function release all resources allocated in the flow list
+ *
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_flow_list_finish(void)
+{
+ bal_sw_flow *current_entry, *p_temp_entry;
+
+ /* Free all the entries in the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &g_swutil_flow_list,
+ flow_next,
+ p_temp_entry)
+ {
+ /* Remove it from the list */
+ TAILQ_REMOVE(&g_swutil_flow_list, current_entry, flow_next);
+
+ bcmos_free(current_entry);
+ }
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The flow list search function by flow id
+ *
+ * @param id Flow id that need to match the entry in the list
+ * @return pointer to an element in the list
+ */
+bal_sw_flow *bal_sw_util_flow_list_get_by_id(uint32_t id)
+{
+ bal_sw_flow *p_entry, *p_temp;
+ TAILQ_FOREACH_SAFE(p_entry, &g_swutil_flow_list, flow_next, p_temp)
+ {
+ if( p_entry->id == id)
+ {
+ break;
+ }
+ }
+ /* if reach the end of the list, TAILQ_FOREACH_SAFE set the p_entry to NULL */
+ return p_entry;
+}
+
+/**
+ * @brief The flow list search function by flow id
+ *
+ * @param trap_code Trap id that need to match the entry in the list
+ * @return pointer to an element in the list
+ */
+bal_sw_flow *bal_sw_util_flow_list_get_by_trap_code(uint32_t trap_code)
+{
+ bal_sw_flow *p_entry, *p_temp;
+
+ if (trap_code == 0)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "Invalid trap code %d in Flow list search by trap code\n", trap_code);
+ return NULL;
+ }
+ TAILQ_FOREACH_SAFE(p_entry, &g_swutil_flow_list, flow_next, p_temp)
+ {
+ if( p_entry->trap_code == trap_code)
+ {
+ break;
+ }
+ }
+ /* if reach the end of the list, TAILQ_FOREACH_SAFE set the p_entry to NULL */
+ return p_entry;
+}
+
+/*
+ * @brief The flow list insert function
+ *
+ * @param entry the element to be added in the link list
+ * @return error code
+*/
+bcmos_errno bal_sw_util_flow_list_insert(bal_sw_flow entry)
+{
+ bal_sw_flow *p_new_entry;
+
+ p_new_entry = bcmos_calloc(sizeof(bal_sw_flow));
+ if(NULL == p_new_entry)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Flow list insert out of memory\n");
+ return BCM_ERR_NOMEM;
+ }
+ *p_new_entry = entry;
+ TAILQ_INSERT_TAIL(&g_swutil_flow_list, p_new_entry, flow_next);
+ return BCM_ERR_OK;
+}
+
+/*
+ * @brief The flow list remove function
+ *
+ * @param p_entry Pointer to the element in the link list result from one of the search functions
+ * @return error code
+*/
+bcmos_errno bal_sw_util_flow_list_remove(bal_sw_flow *p_entry)
+{
+ TAILQ_REMOVE(&g_swutil_flow_list, p_entry, flow_next);
+ bcmos_free(p_entry);
+ return BCM_ERR_OK;
+}
+
+
+/*
+ * @brief down Stream Flow classifier check to see if an ACL rule is needed for classification
+ *
+ * In ING SDK, vswitch LIF is mostly used to classify VLAN and ingress port only.
+ * Any packet classification more than that requires an ACL rule to filter the
+ * traffics. This routine check if an ACL is needed.
+ * If only VLAN ids are classify, return FALSE, otherwise return TRUE
+ *
+ * @param p_flow Pointer to the flow object that contains the classifier
+ * @return TRUE or FALSE
+*/
+bcmos_bool bal_sw_util_flow_ds_acl_cls_chk(bcmbal_flow_cfg *p_flow)
+{
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ether_type) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ip_proto) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_port) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_port) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_pbits) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_pbits) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_mac) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_ip) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_ip)
+ )
+ return BCMOS_TRUE;
+ else
+ return BCMOS_FALSE;
+}
+
+/*
+ * @brief Up Stream Flow classifier check to see if an ACL rule is needed for classification
+ *
+ * In ING SDK, vswitch LIF is mostly used to classify VLAN and ingress port only.
+ * Any packet classification more than that requires an ACL rule to filter the
+ * traffics. This routine check if an ACL is needed.
+ * If only VLAN ids are classify, return FALSE, otherwise return TRUE
+ *
+ * @param p_flow Pointer to the flow object that contains the classifier
+ * @return TRUE or FALSE
+*/
+bcmos_bool bal_sw_util_flow_us_acl_cls_chk(bcmbal_flow_cfg *p_flow)
+{
+ /* Up Stream Outer Pbits classification is done using PON LIF, no need to use ACL */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ether_type) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ip_proto) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_port) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_port) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_pbits) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_mac) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_ip) ||
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_ip)
+ )
+ return BCMOS_TRUE;
+ else
+ return BCMOS_FALSE;
+}
+
+static uint32_t g_flow_inited = 0;
+
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+/**
+ * @brief SWITCH module: flow SET handler
+ *
+ * This routine is called by flow_fsm in the BAL core upon
+ * SET request for flow object.
+ *
+ * @param p_flow Pointer to flow instance
+ * @param opt_type Operation type on flow instance
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_flow_set(flow_inst *p_flow, bal_util_oper_flow opt_type)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ bal_sw_util_vsi_list_init();
+ if (opt_type == BAL_UTIL_OPER_FLOW_ADD)
+ {
+ if (g_flow_inited == 0)
+ {
+ /* initialized the internal flow link list */
+ bal_sw_util_flow_list_init();
+ /* call flow_init in switch device */
+ bal_sw_util_dpp_flow_init();
+ g_flow_inited = 1;
+ }
+ ret = bal_sw_util_flow_add(p_flow);
+ }
+ else if( BAL_UTIL_OPER_FLOW_REMOVE == opt_type )
+ {
+ ret = bal_sw_util_flow_remove(p_flow);
+ }
+ else if( BAL_UTIL_OPER_FLOW_CLEAR == opt_type )
+ {
+ ret = bal_sw_util_flow_remove(p_flow);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Only ADD/REMOVE/CLEAR request is supported for FLOW object\n");
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+#else
+ BCM_LOG(INFO, log_id_sw_util, "dummy flow %s SUCCESS\n",
+ ( BAL_UTIL_OPER_FLOW_ADD == opt_type ) ? "flow add" : "flow remove");
+#endif
+
+ return ret;
+}
+
+/**
+ * @brief SWITCH module: flow clean up function
+ *
+ * This routine is called by bal_switch_util() when the BAL core issue finish request
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_flow_finish()
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ if (g_flow_inited )
+ {
+ /* release the internal flow link list */
+ bal_sw_util_flow_list_finish();
+
+ g_flow_inited = 0;
+ }
+#endif
+ return ret;
+}
+/*@}*/
diff --git a/bal_release/src/core/util/switch/bal_switch_flow.h b/bal_release/src/core/util/switch/bal_switch_flow.h
new file mode 100644
index 0000000..e6d84eb
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_flow.h
@@ -0,0 +1,97 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_flow.h
+ *
+ * @brief Switch flow interfaces header file
+ *
+ * This file expose the APIs to the core to configure the switches
+ * with regarding to the operation of a flow.
+ *
+ * @defgroup sw_util Switch Util
+ * @ingroup core
+ */
+
+#ifndef _BAL_SWITCH_FLOW_H_
+#define _BAL_SWITCH_FLOW_H_
+
+#include <bal_utils_msg.h>
+#include "bcmos_errno.h"
+#include "flow_fsm.h"
+
+/*@{*/
+
+/* Data structure to keep a link list of flow that has been programmed in the switch */
+/* reserve 16 pairs of uni-direction ports */
+#define MAX_PON_PORT 32
+#define MAX_NET_PORT 32
+#define MAX_FIELD_EID 64
+
+#define BAL_SW_FLOW_TYPE_NONE 0
+#define BAL_SW_FLOW_TYPE_DOWNSTREAM (1 << BCMBAL_FLOW_TYPE_DOWNSTREAM)
+#define BAL_SW_FLOW_TYPE_UPSTREAM (1 << BCMBAL_FLOW_TYPE_UPSTREAM)
+#define BAL_SW_FLOW_TYPE_MULTICAST (1 << BCMBAL_FLOW_TYPE_MULTICAST)
+
+typedef struct bal_sw_flow bal_sw_flow;
+struct bal_sw_flow
+{
+ uint32_t id; /* flow id */
+ uint32_t type; /* downstream or upstream */
+ uint32_t device; /* device id, aka unit of the device */
+ uint32_t trap_code; /* id for trap reason */
+ uint32_t trap_port; /* trap gport */
+ uint32_t num_eid;
+ uint32_t field_entry_id[MAX_FIELD_EID]; /* field entry for ACL rules */
+ void *p_vsi_svc; /* vswitch entry in the vsi list */
+ uint32_t vsi_svc_indx; /* index to the service within the vswitch this flow is using */
+ uint32_t svc_port; /* LLId or GEMID */
+ uint32_t num_pon;
+ uint32_t pon_port[MAX_PON_PORT]; /* pon gport attached to vswitch */
+ uint32_t num_net;
+ uint32_t net_port[MAX_NET_PORT]; /* nni gport attached to vswitch */
+ bcmbal_cookie flow_cookie;
+ void *p_service_cfg;
+ uint32_t group_id;
+ uint32_t valid;
+ TAILQ_ENTRY(bal_sw_flow) flow_next;
+};
+
+extern bcmos_errno bal_sw_util_flow_list_insert(bal_sw_flow entry);
+extern bcmos_errno bal_sw_util_flow_list_remove(bal_sw_flow *p_entry);
+extern bal_sw_flow *bal_sw_util_flow_list_get_by_id(uint32_t id);
+extern bal_sw_flow *bal_sw_util_flow_list_get_by_trap_code(uint32_t trap_code);
+extern bcmos_bool bal_sw_util_flow_ds_acl_cls_chk(bcmbal_flow_cfg *p_flow);
+extern bcmos_bool bal_sw_util_flow_us_acl_cls_chk(bcmbal_flow_cfg *p_flow);
+
+/*@}*/
+
+#endif /* _BAL_SWITCH_FLOW_H_ */
diff --git a/bal_release/src/core/util/switch/bal_switch_group.c b/bal_release/src/core/util/switch/bal_switch_group.c
new file mode 100644
index 0000000..4fc020e
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_group.c
@@ -0,0 +1,392 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_group.c
+ * @brief BAL Switch util functions that handle group requests
+ * @addtogroup sw_util
+ */
+
+ /*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bcmos_errno.h"
+#include "bal_switch_util.h" /* include bal_util.msg.h for bal_util_oper_group */
+#include "group_fsm.h" /* for struct group_inst */
+
+
+#include "bal_dpp_group.h"
+#include "bal_switch_acc_term.h"
+
+#ifdef TEST_SW_UTIL_LOOPBACK
+/* nothing to check in loop back mode */
+bcmos_errno sw_util_group_info_validate(void *p_msg)
+{
+ return BCM_ERR_OK;
+}
+
+#else
+/**
+ * @brief The group check function validate the group parameters from the core
+ *
+ * @param p_msg A pointer to the group object to validate
+ * @return error code
+ */
+bcmos_errno sw_util_group_info_validate(void *p_msg)
+{
+ bcmbal_group_cfg *p_grp = (bcmbal_group_cfg *)p_msg;
+ int i, num_of_pon;
+
+ if (p_grp == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " No group specified during validation\n" );
+ return BCM_ERR_PARM;
+ }
+
+ /* if members field is set, make sure the PON interfaces are valid */
+ if (BCMBAL_CFG_PROP_IS_SET(p_grp, group, members))
+ {
+ num_of_pon = bal_bcm_pon_inf_map_size_get();
+ for(i=0; i<p_grp->data.members.len; i++)
+ {
+ bcmbal_group_member_info *p_member = &p_grp->data.members.val[i];
+
+ if (p_member->intf_id >= num_of_pon)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " invalid group member with pon id = %d\n", p_member->intf_id );
+ return BCM_ERR_PARM;
+ }
+ }
+ }
+
+ /* member action is not supported yet */
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The group remove function program switch to release resource that have
+ * been allocated during the group add operation.
+ *
+ * @param p_group_inst A pointer to the group instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_group_remove(group_inst *p_group_inst)
+{
+ bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a group remove request - group_id=%d \n", p_group->key.group_id);
+
+ /* remove must have at least one member */
+ if(p_group->data.members.len == 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group remove request must have at least one member\n");
+ return BCM_ERR_PARM;
+ }
+
+ unit = bal_bcm_pon_inf_dev_get(p_group->data.members.val[0].intf_id);
+ dev_type = bal_bcm_dev_type_get(unit);
+
+ /* call the group add function based on device type */
+ if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_group_rem(unit, p_group);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group remove: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return group remove request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+/**
+ * @brief The group add function program switch to add a member interface to the group
+ *
+ * @param p_group_inst A pointer to the group instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_group_add(group_inst *p_group_inst)
+{
+ bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a group add request - group_id=%d \n", p_group->key.group_id);
+
+ /* add must have at least one member */
+ if(p_group->data.members.len == 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group add request must have at least one member\n");
+ return BCM_ERR_PARM;
+ }
+
+ unit = bal_bcm_pon_inf_dev_get(p_group->data.members.val[0].intf_id);
+ dev_type = bal_bcm_dev_type_get(unit);
+
+ /* call the group add function based on device type */
+ if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_group_add(unit, p_group);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group add: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return group add request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+
+/**
+ * @brief The group set function program switch to replace member interfaces of a group
+ *
+ * @param p_group_inst A pointer to the group instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_group_set(group_inst *p_group_inst)
+{
+ bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a group set request - group_id=%d \n", p_group->key.group_id);
+
+ if(p_group->data.members.len == 0)
+ {
+ unit = bal_bcm_dft_dev_get();
+ }
+ else
+ {
+ unit = bal_bcm_pon_inf_dev_get(p_group->data.members.val[0].intf_id);
+ }
+ dev_type = bal_bcm_dev_type_get(unit);
+
+ /* call the group set function based on device type */
+ if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_group_set(unit, p_group);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group set: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return group set request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+/**
+ * @brief The group create function program switch to create an empty group
+ *
+ * @param p_group_inst A pointer to the group instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_group_create(group_inst *p_group_inst)
+{
+ bcmbal_group_cfg *p_group = &p_group_inst->api_req_group_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a group create request - group_id=%d \n", p_group->key.group_id);
+
+
+ /* For now, only one switch device for a system. If multiple devices support is required,
+ need to loop through all devices to create the group */
+ unit = bal_bcm_dft_dev_get();
+ dev_type = bal_bcm_dev_type_get(unit);
+
+ /* call the group create function based on device type */
+ if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ if( NULL == bal_sw_util_dpp_group_create(unit, p_group))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " switch group create failed\n");
+ ret = BCM_ERR_INTERNAL;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group create: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return group create request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+/**
+ * @brief The group destroy function program switch to release all resource used in a group
+ *
+ * @param p_group_inst A pointer to the group instance being referenced
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_group_destroy(group_inst *p_group_inst)
+{
+ bcmbal_group_cfg *p_group = &p_group_inst->current_group_info;
+ bcmos_errno ret = BCM_ERR_OK;
+ int unit;
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a group destroy request - group_id=%d \n", p_group->key.group_id);
+
+
+ /* For now, only one switch device for a system. If multiple devices support is required,
+ need to loop through all devices to create the group */
+ unit = bal_bcm_dft_dev_get();
+ dev_type = bal_bcm_dev_type_get(unit);
+
+ /* call the group destroy function based on device type */
+ if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_group_destroy(unit, p_group);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type found on group destroy: 0x%x\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " Return group destroy request with %d on device 0x%x\n", ret, dev_type );
+
+ return ret;
+}
+
+static uint32_t g_group_inited = 0;
+
+#endif
+/**
+ * @brief SWITCH module: group SET handler
+ *
+ * This routine is called by group_fsm in the BAL core upon
+ * SET request for group object.
+ *
+ * @param p_group_inst Pointer to group instance
+ * @param opt_type Operation type on group instance
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_group_set(group_inst *p_group_inst, bal_util_oper_group opt_type)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ bal_sw_util_vsi_list_init();
+ if (g_group_inited == 0)
+ {
+ /* initialized the internal group link list */
+ bal_sw_util_dpp_group_list_init();
+
+ g_group_inited = 1;
+ }
+
+ if(p_group_inst == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group set request with NULL pointer to the group instance\n");
+ return BCM_ERR_PARM;
+ }
+
+ if (opt_type == BAL_UTIL_OPER_GROUP_CREATE)
+ {
+ ret = bal_sw_util_group_create(p_group_inst);
+ }
+ else if (opt_type == BAL_UTIL_OPER_GROUP_ADD)
+ {
+ ret = bal_sw_util_group_add(p_group_inst);
+ }
+ else if( BAL_UTIL_OPER_GROUP_REMOVE == opt_type )
+ {
+ ret = bal_sw_util_group_remove(p_group_inst);
+ }
+ else if( BAL_UTIL_OPER_GROUP_SET == opt_type )
+ {
+ ret = bal_sw_util_group_set(p_group_inst);
+ }
+ else if( BAL_UTIL_OPER_GROUP_DESTROY == opt_type )
+ {
+ ret = bal_sw_util_group_destroy(p_group_inst);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Only CREATE/ADD/REMOVE/SET/DESTROY request is supported for GROUP object\n");
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+#else
+ BCM_LOG(INFO, log_id_sw_util, "dummy group %s SUCCESS\n",
+ BCMBAL_UTIL_GROUP_OPER_STR_GET(opt_type));
+#endif
+
+ return ret;
+}
+
+/**
+ * @brief SWITCH module: group clean up function
+ *
+ * This routine is called from the bal_switch_util() when Core calls the finish function.
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_group_finish()
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ if (g_group_inited)
+ {
+ /* release the internal group link list */
+ bal_sw_util_dpp_group_list_finish();
+
+ g_group_inited = 0;
+ }
+#endif
+ return ret;
+}
+/*@}*/
+
+
diff --git a/bal_release/src/core/util/switch/bal_switch_interface.c b/bal_release/src/core/util/switch/bal_switch_interface.c
new file mode 100644
index 0000000..cbd9f1b
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_interface.c
@@ -0,0 +1,123 @@
+/******************************************************************************
+ *
+ * <: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 <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_util.h"
+#include "bal_switch_acc_term.h"
+#include "bal_switch_interface.h"
+#include "dpp/bal_dpp_interface.h"
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <bcm/types.h>
+#include <bcm/port.h>
+
+/**
+ * @file bal_dpp_interface.c
+ * @brief BAL Switch util functions that handle interface requests on DUNE PACKET PROCESSOR
+ * @addtogroup sw_util
+ *
+ */
+
+/*@{*/
+
+
+/**
+ * @brief Set up pon interface with DPP
+ *
+ * This routine is called by sw_util_interface_set in the BAL core
+ * to execute DPP specific API for pon interface request
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param opt_type UP/DOWN/RESTART the interface
+ * @return bcmos_errno
+ */
+bcmos_errno bal_sw_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if opt_type )
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key;
+ int unit, intf_id;
+ uint32_t dev_type;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a interface request - interface_id=%d \n", intf_key.intf_id);
+
+ unit = bal_bcm_pon_inf_dev_get(intf_key.intf_id);
+ intf_id = bal_bcm_pon_inf_pbm_get(intf_key.intf_id);
+ dev_type = bal_bcm_dev_type_get(unit);
+
+ /* call the interface set function based on device type */
+ if (dev_type == BCM_DEVICE_KT2)
+ {
+ ret = BCM_ERR_OK;
+ }
+ else if (dev_type == BCM_DEVICE_ARAD || dev_type == BCM_DEVICE_ARAD_PLUS || dev_type == BCM_DEVICE_QAX)
+ {
+ ret = bal_sw_util_dpp_interface_set(p_interface_inst, opt_type);
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " Unknown device type (0x%x)found on interface set\n", dev_type );
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ BCM_LOG(DEBUG, log_id_sw_util, " Return interface set request with %d on %s 0x%x\n", ret,
+ (intf_key.intf_type == BCMBAL_INTF_TYPE_PON ? "pon" : "nni"), intf_id);
+
+ return ret;
+}
+
+/*@}*/
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+
+/**
+ * @brief SWITCH module: interface SET handler
+ *
+ * This routine is called by interface_fsm in the BAL core upon
+ * SET request for interface object.
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param opt_type UP/DOWN/RESTART the interface
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if opt_type)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+ ret = bal_sw_util_interface_set(p_interface_inst, opt_type);
+#else
+ BCM_LOG(INFO, log_id_sw_util, "dummy SUCCESS\n");
+#endif
+
+ return ret;
+}
diff --git a/bal_release/src/core/util/switch/bal_switch_interface.h b/bal_release/src/core/util/switch/bal_switch_interface.h
new file mode 100644
index 0000000..75d54b5
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_interface.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_interface.h
+ *
+ * @brief bal switch interface service function header file
+ *
+ * @addtogroup sw_util
+ */
+
+#ifndef _BAL_BCM_INTERFACE_H_
+#define _BAL_BCM_INTERFACE_H_
+
+/*@{*/
+#include "bcmos_errno.h"
+
+
+extern bcmos_errno bal_sw_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if opt_type);
+
+
+/*@}*/
+
+#endif
diff --git a/bal_release/src/core/util/switch/bal_switch_tm_queue.c b/bal_release/src/core/util/switch/bal_switch_tm_queue.c
new file mode 100755
index 0000000..5c4aa09
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_tm_queue.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_tm_queue.c
+ * @brief BAL Switch util functions that handle tm requests
+ * @addtogroup sw_util
+ */
+
+ /*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+#include "tm_sched_fsm.h"
+
+
+/* sw_util_tm_queue_validate() is called by the Core to validate the attributes of the tm_queue object
+* p_msg a pointer to the object bcmbal_tm_queue_cfg
+*/
+bcmos_errno sw_util_tm_queue_validate(void *p_msg)
+{
+ return BCM_ERR_OK;
+}
+
+/* sw_util_tm_queue_set() is called by the Core to create an instance of TM Queue in the switch
+* p_tm_queue_inst a pointer to the data structure tm_queue_inst that used in the Core to manage
+* the received tm_queue configuration request from the BAL client
+*
+* Required attributes
+* Key - key to unique identify the TM queue and the parent scheduler
+* Max size - queue size
+* Priority - SP priority, if parent scheduler is of type SP
+* Weight - WFQ weight, if parent scheduler is of type WFQ
+*
+* Optional
+* Rate - for rate limit, if not specified default to FULL rate
+*/
+bcmos_errno sw_util_tm_queue_set(tm_queue_inst *p_tm_queue_inst)
+{
+ return BCM_ERR_OK;
+}
+
+/* sw_util_tm_queue_clear() is called by the Core to remove an instance of TM queue in the switch
+* p_tm_queue_inst a pointer to the data structure tm_queue_inst that used in the Core to manage
+* the received tm_queue configuration request from the BAL client
+*
+* Required attributes
+* Key - key to unique identify the TM queue
+*
+* Note: CLEAR request should be rejected if any flow is still referencing it
+*/
+bcmos_errno sw_util_tm_queue_clear(tm_queue_inst *p_tm_queue_inst)
+{
+ return BCM_ERR_OK;
+}
+
+/*@}*/
+
+
diff --git a/bal_release/src/core/util/switch/bal_switch_tm_sched.c b/bal_release/src/core/util/switch/bal_switch_tm_sched.c
new file mode 100644
index 0000000..3412f2e
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_tm_sched.c
@@ -0,0 +1,88 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_tm_sched.c
+ * @brief BAL Switch util functions that handle tm requests
+ * @addtogroup sw_util
+ */
+
+ /*@{*/
+
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+
+#include "tm_sched_fsm.h"
+
+
+
+/* sw_util_tm_sched_validate() is called by the Core to validate the attributes of the tm_sched object
+ * p_msg a pointer to the object bcmbal_tm_sched_cfg
+ */
+bcmos_errno sw_util_tm_sched_validate(void *p_msg)
+{
+ return BCM_ERR_OK;
+}
+
+/* sw_util_tm_sched_set() is called by the Core to create an instance of TM scheduler in the switch
+ * p_tm_sched_inst a pointer to the data structure tm_sched_inst that used in the Core to manage
+ * the received tm_sched configuration request from the BAL client
+ *
+ * Required attributes
+ * Key - key to unique identify the TM sched
+ * Owner types - Interface, Subscriber_Terminal
+** Owner id - id of interface or subscriber terminal
+ * Schedule types - SP, WFQ, SP_WFQ
+** Num_of_priority - 1 - 16
+* TM objects in the schedule_level this TM sched can support */
+bcmos_errno sw_util_tm_sched_set(tm_sched_inst *p_tm_sched_inst)
+{
+ return BCM_ERR_OK;
+}
+
+/* sw_util_tm_sched_clear() is called by the Core to remove an instance of TM scheduler in the switch
+* p_tm_sched_inst a pointer to the data structure tm_sched_inst that used in the Core to manage
+* the received tm_sched configuration request from the BAL client
+*
+* Required attributes
+* Key - key to unique identify the TM sched
+*/
+bcmos_errno sw_util_tm_sched_clear(tm_sched_inst *p_tm_sched_inst)
+{
+ return BCM_ERR_OK;
+}
+/*@}*/
+
+
+
diff --git a/bal_release/src/core/util/switch/bal_switch_util.c b/bal_release/src/core/util/switch/bal_switch_util.c
new file mode 100644
index 0000000..696295f
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_util.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_util.c
+ *
+ * @brief Switch App interfaces definition used by Bal Core
+ *
+ * This file provides CmdSet message handler functions with relevant
+ * bal object operations of access terminal and flow.
+ *
+ * @addtogroup sw_util
+ *
+ */
+
+/*@{*/
+
+#include <bcm_dev_log.h>
+#include <bal_common.h>
+#include <bal_msg.h>
+#include "bal_switch_util.h"
+
+/*
+ * Logging device id
+ */
+dev_log_id log_id_sw_util;
+
+/**
+* @brief sw_util_init routine to initialize the switch util before any use
+* @return bcmos_errno
+*/
+bcmos_errno sw_util_init(void)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ log_id_sw_util = bcm_dev_log_id_register("SW_UTIL", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_sw_util== DEV_LOG_INVALID_ID);
+
+ return rc;
+}
+
+/**
+* @brief sw_util_finish routine to release any resource used by the switch util before exit
+* @return bcmos_errno
+*/
+bcmos_errno sw_util_finish(void)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ /* release any internal allocated DB - best effort as we are exiting anyway */
+ /* flow */
+ sw_util_flow_finish();
+
+ /* group */
+ sw_util_group_finish();
+
+ return rc;
+}
+
+/*@}*/
+
diff --git a/bal_release/src/core/util/switch/bal_switch_util.h b/bal_release/src/core/util/switch/bal_switch_util.h
new file mode 100644
index 0000000..a33a2ac
--- /dev/null
+++ b/bal_release/src/core/util/switch/bal_switch_util.h
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_switch_util.h
+ *
+ * @brief Switch App interfaces header file
+ *
+ * This file expose the APIs to the core to configure the switchs
+ * with regarding to the operation of access terminal and flow.
+ *
+ * @defgroup sw_util Switch Util
+ * @ingroup core
+ */
+
+#ifndef _BAL_SWITCH_UTIL_H_
+#define _BAL_SWITCH_UTIL_H_
+
+/*@{*/
+
+#include <acc_term_fsm.h>
+#include <flow_fsm.h>
+#include <group_fsm.h>
+#include <tm_sched_fsm.h>
+#include <tm_queue_fsm.h>
+
+
+#include <bcmcli.h>
+#include <bal_utils_msg.h>
+
+#define BCM_DEVICE_KT2 0xb450
+#define BCM_DEVICE_ARAD_PLUS 0x8660
+#define BCM_DEVICE_ARAD 0x8650
+#define BCM_DEVICE_QAX 0x8470
+
+/* Function Prototypes for external */
+bcmos_errno sw_util_access_terminal_set(acc_term_inst *p_acc_term, bal_util_oper_acc_term opt_type);
+bcmos_errno sw_util_flow_info_validate(void *p_msg);
+bcmos_errno sw_util_flow_set(flow_inst *p_flow, bal_util_oper_flow opt_type);
+bcmos_errno sw_util_flow_finish(void);
+bcmos_errno sw_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if opt_type);
+bcmos_errno sw_util_group_info_validate(void *p_msg);
+bcmos_errno sw_util_group_set(group_inst *p_group_inst, bal_util_oper_group opt_type);
+bcmos_errno sw_util_group_finish(void);
+bcmos_errno sw_util_init(void);
+bcmos_errno sw_util_cli_init(bcmcli_entry *top_dir);
+bcmos_errno sw_util_finish(void);
+
+
+bcmos_errno sw_util_tm_sched_validate(void *p_msg);
+bcmos_errno sw_util_tm_sched_set(tm_sched_inst *p_tm_sched_inst);
+bcmos_errno sw_util_tm_sched_clear(tm_sched_inst *p_tm_sched_inst);
+
+bcmos_errno sw_util_tm_queue_validate(void *p_msg);
+bcmos_errno sw_util_tm_queue_set(tm_queue_inst *p_tm_queue_inst);
+bcmos_errno sw_util_tm_queue_clear(tm_queue_inst *p_tm_queue_inst);
+
+
+/* switch util log id */
+extern dev_log_id log_id_sw_util;
+
+/*@}*/
+
+#endif /* _BAL_SWITCH_UTIL_H_ */
+
diff --git a/bal_release/src/core/util/switch/dpp/Makefile b/bal_release/src/core/util/switch/dpp/Makefile
new file mode 100644
index 0000000..5da000b
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/Makefile
@@ -0,0 +1,46 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# BAL Switch Util DPP
+MOD_NAME = switch_util_dpp
+MOD_TYPE = lib
+MOD_DEPS = dev_log utils bal_api bal_app_utils
+srcs = bal_dpp_acc_term.c bal_dpp_flow.c bal_dpp_interface.c bal_dpp_qos.c bal_dpp_qos_map.c bal_dpp_vswitch.c bal_dpp_group.c
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../../main -I$(SRC_DIR)/..
+
+ifeq ("$(TEST_SW_UTIL_LOOPBACK)", "y")
+ MOD_DEFS += -DTEST_SW_UTIL_LOOPBACK
+else
+ MOD_DEPS += switch_sdk
+endif
+
+ifeq ("$(SWITCH)", "qax")
+ MOD_DEFS += -DQAX_SWITCH
+endif
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_acc_term.c b/bal_release/src/core/util/switch/dpp/bal_dpp_acc_term.c
new file mode 100755
index 0000000..42a9e95
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_acc_term.c
@@ -0,0 +1,624 @@
+/******************************************************************************
+ *
+ * <: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 TEST_SW_UTIL_LOOPBACK
+
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_util.h"
+#include "bal_switch_acc_term.h"
+#include "bal_dpp_acc_term.h"
+#include "bal_dpp_qos.h"
+#include "bal_dpp_qos_map.h"
+
+#include <bcm/types.h>
+#include <bcm/port.h>
+#include <bcm/rx.h> /* for dpp rpc rx register callback */
+#include <bcm/switch.h>
+#include <bcm/l2.h>
+
+/**
+ * @file bal_dpp_acc_term.c
+ * @brief BAL Switch util functions that handle access terminal requests on DUNE PACKET PROCESSOR
+ * @addtogroup sw_util
+ *
+ */
+
+/*@{*/
+
+ /* @brief L2 Table Operation Control
+ *
+ * This routine set the HW L2 learning and aging
+ *
+ * @param unit The device id
+ * @param flags Operation flags
+ * BCM_L2_LEARN_CPU 0x20
+ * BCM_L2_INGRESS_DIST 0x02
+ * BCM_L2_INGRESS_CENT 0x01
+ * @param age_seconds L2 entry age out time in seconds
+ * @return BCM error code
+ */
+static int sw_util_dpp_l2_entry_control_set(int unit, int flags, int age_seconds)
+{
+ int rv = 0;
+
+ rv = bcm_switch_control_set(unit, bcmSwitchL2LearnMode, flags);
+ if (rv)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " bcm_switch_control_set failed ret = %d\n", rv);
+ return rv;
+ }
+
+ /* set aging time */
+ rv = bcm_l2_age_timer_set(unit, age_seconds);
+ if (rv)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " bcm_l2_age_timer_set failed ret = %d\n", rv);
+ return rv;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, " Set L2 table aging time to %d seconds\n", age_seconds);
+ }
+
+ return rv;
+
+}
+
+
+/**
+ * @brief L2 Table event handler
+ *
+ * This routine is a callback triggered by HW L2 Table events
+ *
+ * @param unit The device id
+ * @param p_l2addr Pointer to the L2 entry where the event is happen
+ * @param operation The type of event
+ * @param userdata Pointer to a user provided data when the handler is registered
+ */
+static void sw_util_dpp_l2_entry_event_handler(int unit, bcm_l2_addr_t *p_l2addr, int operation, void *userdata)
+{
+
+ if (p_l2addr == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " L2 entry callback with NULL L2 address, op = %d\n", operation);
+ return;
+ }
+ if (operation == BCM_L2_CALLBACK_LEARN_EVENT)
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_LEARN_EVENT handler\n");
+ }
+ else if (operation == BCM_L2_CALLBACK_MOVE_EVENT)
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_MOVE_EVENT handler\n");
+ }
+ else if (operation == BCM_L2_CALLBACK_AGE_EVENT)
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_AGE_EVENT handler\n");
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " BCM_L2_CALLBACK_OPERATION %d handler\n", operation);
+ }
+
+ BCM_LOG(DEBUG, log_id_sw_util, " MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
+ (0xff & p_l2addr->mac[0]),
+ (0xff & p_l2addr->mac[1]),
+ (0xff & p_l2addr->mac[2]),
+ (0xff & p_l2addr->mac[3]),
+ (0xff & p_l2addr->mac[4]),
+ (0xff & p_l2addr->mac[5]) );
+
+ if(!(p_l2addr->flags & BCM_L2_MCAST))
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " UC VID=0x%x| PORT=0x%08x\n", p_l2addr->vid, p_l2addr->port);
+ /* print_gport_part - p_l2addr->port */
+ {
+ int a = -1, b = 0;
+ char* type = "";
+ if (a==-1){
+ a=BCM_GPORT_LOCAL_GET(p_l2addr->port);
+ type ="local";
+ }
+ if (a==-1){
+ a=BCM_GPORT_MODPORT_MODID_GET(p_l2addr->port);
+ b=BCM_GPORT_MODPORT_PORT_GET(p_l2addr->port);
+ type ="modport";
+ }
+ if (a==-1){
+ a=BCM_GPORT_TRUNK_GET(p_l2addr->port);
+ type ="trunk";
+ }
+ if (a==-1){
+ a=BCM_GPORT_MCAST_GET(p_l2addr->port);
+ type ="mact";
+ }
+ if (a==-1){
+ a=BCM_GPORT_MPLS_PORT_ID_GET(p_l2addr->port);
+ type ="mpls_port";
+ }
+ if (a==-1){
+ a=BCM_GPORT_VLAN_PORT_ID_GET(p_l2addr->port);
+ type ="vlan_port";
+ }
+ if (a==-1){
+ a=BCM_GPORT_SYSTEM_PORT_ID_GET(p_l2addr->port);
+ type ="sys_port";
+ }
+ if (a==-1){
+ a=BCM_GPORT_MIRROR_GET(p_l2addr->port);
+ }
+ BCM_LOG(DEBUG, log_id_sw_util, " GPORT %s <0x%x,%d>\n", type, a, b);
+ }
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, " MC 0x%08x\n",p_l2addr->l2mc_group);
+ }
+ BCM_LOG(DEBUG, log_id_sw_util, " static %d|\n", (p_l2addr->flags & BCM_L2_STATIC)!=0 );
+
+}
+
+/**
+ * @brief Connect access terminal with DPP as part of the components
+ *
+ * This routine is called by sw_util_access_terminal_connect in the BAL core
+ * to execute DPP specific API for access_terminal_connect request
+ *
+ * @param p_net_map Pointer to the net ports mapping from logical numbrer to physical number
+ * @param p_pon_map Pointer to the pon ports mapping from logical numbrer to physical number
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_dpp_acc_term_connect(bal_swapp_port *p_net_map, bal_swapp_port *p_pon_map )
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ int rc = 0;
+ bal_swapp_port *port;
+
+ BCM_LOG(INFO, log_id_sw_util, " DPP - Got a access terminal CONNECT\n");
+
+ do
+ {
+ /* setup the device ID - This is very hardware specific */
+ port = p_net_map;
+ /* -1 indicate the end of table */
+ while(port->pbm_id != -1)
+ {
+
+ /* the default TPID is 0x8100, add 0x88a8 to the allow TPID */
+
+ rc = bcm_port_tpid_delete_all(port->device_id, port->pbm_id);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to clear the nni TPID list on interface %d\n", port->pbm_id);
+ ret = BCM_ERR_INTERNAL;
+ }
+ rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x8100, 0);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x8100 to the nni TPID list on interface %d\n", port->pbm_id);
+ ret = BCM_ERR_INTERNAL;
+ }
+ rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x88a8, 0);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x88a8 to the nni TPID list on interface %d\n", port->pbm_id);
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ port++;
+ }
+
+ port = p_pon_map;
+ while(port->pbm_id != -1)
+ {
+
+ /* the default TPID is 0x8100, add 0x88a8 to the allow TPID */
+
+ rc = bcm_port_tpid_delete_all(port->device_id, port->pbm_id);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to clear the pon TPID list on interface %d\n", port->pbm_id);
+ ret = BCM_ERR_INTERNAL;
+ }
+ rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x8100, 0);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x8100 to the pon TPID list on interface %d\n", port->pbm_id);
+ ret = BCM_ERR_INTERNAL;
+ }
+ rc = bcm_port_tpid_add(port->device_id, port->pbm_id, 0x88a8, 0);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to add 0x88a8 to the pon TPID list on interface %d\n", port->pbm_id);
+ ret = BCM_ERR_INTERNAL;
+ }
+
+ port++;
+ }
+
+ if(ret != BCM_ERR_OK)
+ {
+ /* exit if port init failed */
+ break;
+ }
+
+ /* Remove all ports from VLAN 1, so the L2 broadcast won't send to CPU port by default */
+ bcm_vlan_gport_delete_all(bal_bcm_dft_dev_get(), 1);
+
+ /* configure all qos map tables */
+ ret = bal_sw_dpp_pcp_remark_maps_init(bal_bcm_dft_dev_get());
+ if (ret)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to init qos map tables\n");
+ break;
+ }
+
+ /* init the DS QOS hierarchical scheduling - ignore error if HW dos not support QOS */
+ ret =bal_sw_dpp_qos_init(bal_bcm_dft_dev_get(), bal_bcm_intf_maptable_get());
+ if (ret)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to init qos HR scheduler\n");
+ break;
+ }
+
+ rc = bcm_l2_addr_register(bal_bcm_dft_dev_get(), sw_util_dpp_l2_entry_event_handler, NULL);
+ if (rc)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to register l2_addr callback \n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ rc = sw_util_dpp_l2_entry_control_set(bal_bcm_dft_dev_get(), BCM_L2_LEARN_CPU|BCM_L2_INGRESS_DIST, bal_bcm_l2_age_time_get());
+ if (rc)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " DPP - fail to set l2_addr control \n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }while(0);
+ return ret;
+}
+
+/* internal structure used by the trap receiving thread */
+typedef struct
+{
+ int udp_port;
+ pthread_t threadid;
+ dpp_rx_cb_f callback;
+} trap_context;
+
+static trap_context g_trap_ctx = {0};
+
+/* the adjustment needed for ING trap packet header */
+#define DEFAULT_SOP_ADJ 2
+#define DEFAULT_REASON_ADJ 4
+/* compiler restirct the total local variables size < 16384 */
+#define DEFAULT_TRAP_BUF_SIZE (10 *1024)
+/*
+ the listener thread that wait for the trap packet_in message from the switch
+*/
+static void *trap_receive(void *p_user_data)
+{
+ int rc;
+ int sUDPSocket;
+ unsigned char cBuffer[DEFAULT_TRAP_BUF_SIZE];
+ int nBytesRecv = 0;
+ int nBufSize = DEFAULT_TRAP_BUF_SIZE;
+ socklen_t nReceiveAddrSize = 0;
+ int maxfd;
+ fd_set read_fds;
+ struct timeval tv;
+ uint16_t tmp_src_port, src_port;
+ trap_context *p_trap_ctx = (trap_context *)p_user_data;
+ uint32_t tmp_reason, reason;
+ /* Create a connectionless socket */
+ sUDPSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ /* Check to see if we have a valid socket */
+ if(sUDPSocket < 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - trap_receive:create socket failed\n");
+ return NULL;
+ }
+
+ // Setup a bind on the socket, telling us what port and
+ // adapter to receive datagrams on.
+ struct sockaddr_in sReceiveFromAddr;
+ memset(&sReceiveFromAddr, 0, sizeof(struct sockaddr_in));
+
+ sReceiveFromAddr.sin_family = AF_INET;
+ sReceiveFromAddr.sin_port = htons(p_trap_ctx->udp_port);
+ sReceiveFromAddr.sin_addr.s_addr = htonl(INADDR_ANY);
+
+ rc = bind(sUDPSocket, (struct sockaddr *)&sReceiveFromAddr,
+ sizeof(struct sockaddr_in));
+ if (rc < 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - trap_receive:bind failed\n");
+ return NULL;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, " DPP - trap_receive start listen at %d\n", p_trap_ctx->udp_port);
+
+ // Receive a datagram from another device
+ while(1)
+ {
+ FD_ZERO(&read_fds);
+ FD_SET(sUDPSocket, &read_fds);
+ maxfd = sUDPSocket;
+ /* Set the timeout */
+ tv.tv_sec = 3;
+ tv.tv_usec = 0; /* 3 seconds */
+ rc = select(maxfd + 1, &read_fds, NULL, NULL, &tv);
+
+ if (rc < 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - trap_receive:select failed err = %d\n", rc);
+ break;
+ }
+ if (rc == 0) /* timeout */
+ {
+ continue;
+ }
+ // Get the datagrama
+ nBytesRecv = recvfrom(sUDPSocket, cBuffer, nBufSize, 0,
+ (struct sockaddr *) &sReceiveFromAddr,
+ &nReceiveAddrSize);
+ BCM_LOG(INFO, log_id_sw_util, " DPP - Got %d bytes message \n", nBytesRecv);
+
+ /* the first 4 bytes are reason */
+ /* compiler generate cast-align warning -> p_reason = (uint32_t *)(cBuffer); */
+ memcpy(&tmp_reason, cBuffer, sizeof(uint32_t) );
+ reason = ntohl(tmp_reason);
+ /* the next 2 bytes are srouce port */
+ /* compiler generate cast-align warning -> p_src_port = (uint16 *)(cBuffer + DEFAULT_REASON_ADJ); */
+ memcpy(&tmp_src_port, cBuffer + DEFAULT_REASON_ADJ, sizeof(uint16_t));
+ src_port = ntohs(tmp_src_port);
+
+ /* call the register callback here - set unit to 0 as it is don't care */
+ if(p_trap_ctx->callback)
+ {
+ p_trap_ctx->callback(0, src_port, reason, cBuffer+DEFAULT_SOP_ADJ+DEFAULT_REASON_ADJ, nBytesRecv-DEFAULT_SOP_ADJ-DEFAULT_REASON_ADJ);
+ }
+ }
+ close(sUDPSocket);
+
+ return NULL;
+}
+
+/**
+ * @brief Start a receiving thread and add the callbck to process CPU trapped packets
+ *
+ * This routine is called by sw_util_access_terminal_connect in the BAL core
+ * to execute DPP specific API for process the trapping packets
+ *
+ * @param unit the switch device number the callback applied
+ * @param cb_f a callback function that process the trapped packets
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_dpp_rx_cb_register(uint32_t unit, dpp_rx_cb_f cb_f)
+{
+ int ret;
+
+ /* if the receiving thread already started, return error */
+ if (g_trap_ctx.threadid)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - There is an existing trap receiving thread\n");
+ return BCM_ERR_INTERNAL;
+ }
+
+ g_trap_ctx.udp_port = bal_bcm_trap_rcv_port_get();
+ g_trap_ctx.callback = cb_f;
+
+ /* use default attribute to create the thread */
+ ret = pthread_create(&g_trap_ctx.threadid, NULL, &trap_receive, &g_trap_ctx);
+
+ if(ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " DPP - fail to create trap receiving thread - %d\n", ret);
+ return BCM_ERR_INTERNAL;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/* To make compiler happy when build with ESW switch only */
+#ifdef ESW_SWITCH
+void dpp_dft_rx_cb(int unit, int dst_port, int reason, unsigned char *payload, int payload_len)
+{
+ return;
+}
+#else
+extern void dpp_dft_rx_cb(int unit, int dst_port, int reason, unsigned char *payload, int payload_len);
+#endif
+
+#define L2_HEADER_SIZE (12) /* bytes */
+
+#define TUNNEL_TAG_TPID_LEN (2) /* bytes - TPID (2 bytes) */
+#define TUNNEL_TAG_PBITS_CFI_VLAN_ID_LEN (2) /* PBITS+CFI+VLAN ID (2 bytes) */
+#define TUNNEL_TAG_SIZE (TUNNEL_TAG_TPID_LEN + TUNNEL_TAG_PBITS_CFI_VLAN_ID_LEN)
+
+bcmos_errno sw_util_dpp_pkt_send(int target_port_id,
+ int reason,
+ unsigned char *p_user_pkt,
+ int user_pkt_len,
+ trap_target target_device,
+ int target_tunnel_id)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ char *p_pktout_msg;
+ uint8_t dst_port_id;
+ int dst_device_id;
+ char *p_pktout_ptr;
+ uint32_t total_msg_size;
+ uint32_t uint32_num;
+ uint16_t uint16_num;
+
+ /*
+ * Allocate a message to be sent to the bcm.user instance. This will contain
+ * the packet to be sent out of the switch, as well has header metadata.
+ */
+ p_pktout_msg = bcmos_calloc(user_pkt_len +
+ DEFAULT_SOP_ADJ +
+ DEFAULT_REASON_ADJ +
+ TUNNEL_TAG_SIZE);
+
+ if(NULL == p_pktout_msg)
+ {
+ return BCM_ERR_NOMEM;
+ }
+
+ /* translate the output port to the bcm.user's mapping */
+ switch(reason)
+ {
+ case REASON_SEND_TO_NNI:
+ dst_port_id = bal_bcm_net_inf_pbm_get(target_port_id);
+ dst_device_id = bal_bcm_net_inf_dev_get(target_port_id);
+ break;
+ case REASON_SEND_TO_PON:
+ dst_port_id = bal_bcm_pon_inf_pbm_get(target_port_id);
+ dst_device_id = bal_bcm_pon_inf_dev_get(target_port_id);
+ break;
+ default:
+ return BCM_ERR_PARM;
+ break;
+ }
+
+ /* Format of the message to the bcm.user instance is:
+ *
+ * reason code: 4 bytes
+ * dst_port: 2 bytes
+ * user packet: pkt_size bytes
+ */
+
+ /* Insert the 4 bytes with reason code */
+ uint32_num = (htonl(reason));
+ memcpy(p_pktout_msg, &uint32_num, sizeof(uint32_num));
+
+ /* Replace 2 bytes with packet_out destination port info. This is the bcm.user's
+ * mapping of output port (NNI or PON) to BCM SDK port mapping */
+ uint16_num = htons(dst_port_id & 0xff); /* dst_port contents is actually only 1 byte */
+ memcpy(&p_pktout_msg[DEFAULT_REASON_ADJ], &uint16_num, sizeof(uint16_num));
+
+ /* Copy in the user packet to send to the bcm.user for transmission out of the switch.
+ * Remember to insert the proper tunnel tag in the message for out_ports that are
+ * associated with the PON
+ */
+ p_pktout_ptr = p_pktout_msg + DEFAULT_REASON_ADJ + DEFAULT_SOP_ADJ;
+ total_msg_size = user_pkt_len + DEFAULT_REASON_ADJ + DEFAULT_SOP_ADJ;
+
+ if(reason == REASON_SEND_TO_NNI)
+ {
+ /* Copy in the entire packet as-is */
+ memcpy(p_pktout_ptr, p_user_pkt, user_pkt_len);
+ }
+ else
+ {
+ uint16_t pktout_offset = 0;
+
+ /* Copy in the L2 header (MAC DA/SA) */
+ memcpy(&p_pktout_ptr[pktout_offset], p_user_pkt, L2_HEADER_SIZE);
+
+ /* Point to the tunnel tag area in the outgoing message */
+ pktout_offset += L2_HEADER_SIZE;
+
+ /* Insert the TPID in the tag for the output destination */
+ uint16_num = htons(0x8100);
+ memcpy(&p_pktout_ptr[pktout_offset], &uint16_num, sizeof(uint16_num));
+
+ /* Point to the remainder of the outgoing message */
+ pktout_offset += TUNNEL_TAG_TPID_LEN;
+ /* Insert the tunnel tag vlan ID for the output destination */
+ uint16_num = htons(target_tunnel_id);
+ memcpy(&p_pktout_ptr[pktout_offset], &uint16_num, sizeof(uint16_num));
+
+ /* Point to the remainder of the outgoing message */
+ pktout_offset += TUNNEL_TAG_PBITS_CFI_VLAN_ID_LEN;
+
+ /* Copy in the rest of the message */
+ memcpy(&p_pktout_ptr[pktout_offset],
+ (p_user_pkt + L2_HEADER_SIZE),
+ (user_pkt_len - L2_HEADER_SIZE));
+
+ total_msg_size += TUNNEL_TAG_SIZE;
+ }
+
+
+ BCM_LOG(DEBUG, log_id_sw_util, "Packet send (user pkt_size:%d) destined for %s port %d\n",
+ user_pkt_len,
+ (reason == REASON_SEND_TO_PON) ? "PON" : "NNI",
+ dst_port_id);
+
+ if(reason == REASON_SEND_TO_PON)
+ {
+ BCM_LOG(DEBUG, log_id_sw_util, "Sending via GEM %d\n", target_tunnel_id);
+ }
+
+ if (bal_bcm_use_rpc_get())
+ {
+ /* On systems where BAL runs remotely from the switch hardware, we
+ * send the packet out message to the remote bcm.user process.
+ * That process then sends the attached user packet to the specified switch port.
+ */
+
+ sendto(target_device.socket,
+ p_pktout_msg,
+ total_msg_size, 0,
+ (struct sockaddr *) &(target_device.addr),
+ sizeof(struct sockaddr_in));
+
+ }
+ else
+ {
+ /* On systems where BAL runs on the CPU co-located with the switch hardware,
+ * we send the attached user packet to the specified switch port directly.
+ */
+
+ total_msg_size = total_msg_size - ( DEFAULT_REASON_ADJ + DEFAULT_SOP_ADJ );
+ dpp_dft_tx_cb(dst_device_id,
+ dst_port_id,
+ reason,
+ (unsigned char *)p_pktout_ptr,
+ total_msg_size);
+ }
+
+ bcmos_free(p_pktout_msg);
+
+ BCM_LOG(INFO, log_id_sw_util, "CPU packet msg sent to bcm.user for packet with msg size of %d (payload size: %d)\n",
+ total_msg_size, user_pkt_len);
+
+ return ret;
+}
+
+/*@}*/
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_acc_term.h b/bal_release/src/core/util/switch/dpp/bal_dpp_acc_term.h
new file mode 100755
index 0000000..4f71549
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_acc_term.h
@@ -0,0 +1,63 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_acc_term.h
+ *
+ * @brief bal switch util access terminal service function header file for DUNE PACKET PROCESSOR
+ *
+ * @addtogroup sw_util
+ */
+
+#ifndef _BAL_DPP_ACC_TERM_H_
+#define _BAL_DPP_ACC_TERM_H_
+
+/*@{*/
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+#include "bal_switch_acc_term.h"
+
+extern bcmos_errno sw_util_dpp_acc_term_connect(bal_swapp_port *p_net_map, bal_swapp_port *p_pon_map);
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <bcm/rx.h> /* for dpp rpc rx register callback */
+extern bcmos_errno sw_util_dpp_rx_cb_register(uint32_t unit, dpp_rx_cb_f cb_f);
+
+bcmos_errno sw_util_dpp_pkt_send(int dst_port_id,
+ int reason,
+ unsigned char *payload,
+ int payload_len,
+ trap_target target_device,
+ int target_tunnel_id);
+#endif /* TEST_SW_UTIL_LOOPBACK */
+/*@}*/
+
+#endif
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_flow.c b/bal_release/src/core/util/switch/dpp/bal_dpp_flow.c
new file mode 100755
index 0000000..bf8067c
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_flow.c
@@ -0,0 +1,2618 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_flow.c
+ * @brief BAL Switch util functions that handle flow requests
+ * @addtogroup sw_util
+ */
+
+ /*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include <bal_utils_msg.h>
+#include "bal_switch_flow.h"
+#include "flow_fsm.h"
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+#include "bal_dpp_qos_map.h"
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#define _SHR_PBMP_WIDTH 567
+ /* match the WIDTH size of bcm_field_group_config_t in bcm/field.h with ARAD */
+ /* we build swich_util without #define created by the sdk make/Make.local */
+#include <bcm/types.h>
+#include <sal/core/libc.h>
+#ifndef sal_memset
+#define sal_memset memset
+#endif
+#include <bcm/port.h>
+#include <bcm/vlan.h>
+#include <bcm/field.h>
+#include <bcm/error.h>
+#include <bcm/vswitch.h>
+#include <bcm/qos.h>
+#include <bcm/l2.h>
+
+#include "bal_switch_acc_term.h"
+#include "bal_dpp_flow.h"
+#include "bal_dpp_qos.h"
+#include "bal_dpp_vswitch.h"
+#include "bal_dpp_group.h"
+
+/** Local routines declarations */
+static bcmos_errno bal_sw_util_reverse_flow_create(bcmbal_flow_cfg *p_flow, bcmbal_flow_cfg *p_flow_rev);
+static bcmos_bool bal_sw_util_is_symmetry_flows(bcmbal_flow_cfg *p_flow, bcmbal_flow_cfg *p_ref_flow);
+
+/* perform initialization before any dpp flow function calls */
+void bal_sw_util_dpp_flow_init(void)
+{
+ /* nothing to do here yet, place holder */
+ return;
+}
+
+/**
+ * @brief The create trap gport function create a trap port that allow TRAP action to
+ * associate with and perform packet trapping to the CPU port.
+ *
+ * @param unit the switch unit this trap port to be created
+ * @param p_trap_gport a pointer that the created gport will be return
+ * @param p_trap_code a pointer that the created trap code will be return
+ * @return bcm error code
+ */
+static int bal_sw_util_create_trap_gport(int unit, bcm_gport_t *p_trap_gport, uint32_t *p_trap_code)
+{
+ int ret, trap_id;
+ bcm_rx_trap_config_t trap_config;
+
+ ret = bcm_rx_trap_type_create(unit, 0, bcmRxTrapUserDefine, &trap_id);
+ if(ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "create trap type return %d\n", ret);
+ return ret;
+ }
+
+ bcm_rx_trap_config_t_init(&trap_config);
+ trap_config.flags = (BCM_RX_TRAP_UPDATE_DEST | BCM_RX_TRAP_TRAP | BCM_RX_TRAP_REPLACE);
+ trap_config.trap_strength = 0;
+ trap_config.dest_port = BCM_GPORT_LOCAL_CPU;
+ ret = bcm_rx_trap_set(unit, trap_id, &trap_config);
+ if(ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "set rx trap return %d\n", ret);
+ return ret;
+ }
+ BCM_GPORT_TRAP_SET(*p_trap_gport, trap_id, 7 /* trap_strength */, 0);
+ *p_trap_code = trap_id;
+ return ret;
+}
+/* disable the field group (FG) source ip support to restrict the FG size */
+#define BAL_ACL_FG_SRC_IP_ENABLE 0
+/* create a default field group that used by all default ACL.
+ When a FLOW is created,a LIF is created to direct the packets to a VSwitch.
+ The LIF can only match packet with ingress port and VID.
+ If a FLOW needs to be classified with more attributes, an ACL is created to override the LIF.
+ A default ACL has the same packet classification as the LIF but has lower priority than the overlapped ACL.
+ The default ACL dropped packets that match the LIF but do not match the ACL. This enforce the FLOW
+ to only forward packets with exact match */
+static bcm_field_group_t dpp_dft_group_id = 1;
+/* create a field group that used by all ACL */
+static bcm_field_group_t dpp_group_id = 0;
+/**
+ * @brief Create a field group in the switch ICAP,
+ * The field group allow flow classifier to create ACL rules
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_group_id a pointer to a variable that return the created group id
+ * @return error code
+ */
+ static bcmos_errno bal_sw_util_dpp_fg_create(int unit, bcm_field_group_t *p_group_id)
+ {
+ bcm_field_group_status_t fg_status;
+ bcm_field_group_config_t grp;
+ int32_t ret = 0;
+
+ /* VCAP - bcmFieldQualifyStageLookup, ICAP - bcmFieldQualifyStageIngress, ECAP - bcmFieldQualifyStageEgress */
+ /* The DPP resources allow only limit number of qset - indexed by dpp_group_id, create qset when necessary */
+ /* create one if not exist */
+ if (BCM_E_NOT_FOUND == bcm_field_group_status_get(unit, *p_group_id, &fg_status))
+ {
+ bcm_field_group_config_t_init(&grp);
+
+ BCM_FIELD_QSET_INIT(grp.qset);
+ /* TCAM entry limit to 80 bits per slice, but up to 4 slices for a group
+ use ModeAuto to automatically adjust it */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyInPort); /* 32 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyDstMac); /* 48 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifySrcMac); /* 48 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyDstIp); /* 32 bits */
+#if (BAL_ACL_FG_SRC_IP_ENABLE == 1)
+ /* save source IP space for other classifier, try to keep total size under 4 slices */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifySrcIp); /* 32 bits */
+#endif
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyEtherType); /* 16 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyIpProtocol); /* 8 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyL4DstPort); /* 16 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyL4SrcPort); /* 16 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyOuterVlanId); /* 16 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyOuterVlanPri); /* 8 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyInnerVlanId); /* 16 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyInnerVlanPri); /* 8 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyInVPort); /* 32 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyPacketRes);
+
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyStageIngress);
+
+ BCM_FIELD_ASET_INIT(grp.aset);
+ BCM_FIELD_ASET_ADD(grp.aset, bcmFieldActionTrap);
+ BCM_FIELD_ASET_ADD(grp.aset, bcmFieldActionDrop);
+ BCM_FIELD_ASET_ADD(grp.aset, bcmFieldActionRedirect);
+ BCM_FIELD_ASET_ADD(grp.aset, bcmFieldActionVportNew);
+
+ grp.priority = 12; /* the higher the number the higher the priority */
+ grp.flags = (BCM_FIELD_GROUP_CREATE_WITH_MODE | BCM_FIELD_GROUP_CREATE_WITH_ASET);
+ grp.mode = bcmFieldGroupModeAuto;
+
+ ret = bcm_field_group_config_create(unit, &grp);
+
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to create field - %d\n", ret );
+ return BCM_ERR_INTERNAL;
+ }
+
+ *p_group_id = grp.group;
+ BCM_LOG(INFO, log_id_sw_util, "Field Group %d created\n", *p_group_id);
+ return BCM_ERR_OK;
+ }
+ return BCM_ERR_ALREADY;
+ }
+
+/**
+ * @brief Create a default field group in the switch ICAP,
+ * This field group allow flow classifier to create default ACL rules
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_group_id a pointer to a variable that return the created group id
+ * @return error code
+ */
+ static bcmos_errno bal_sw_util_dpp_dft_fg_create(int unit, bcm_field_group_t *p_group_id)
+ {
+ bcm_field_group_status_t fg_status;
+ bcm_field_group_config_t grp;
+ int32_t ret = 0;
+
+ /* VCAP - bcmFieldQualifyStageLookup, ICAP - bcmFieldQualifyStageIngress, ECAP - bcmFieldQualifyStageEgress */
+ /* The DPP resources allow only limit number of qset - indexed by dpp_group_id, create qset when necessary */
+ /* create one if not exist */
+ if (BCM_E_NOT_FOUND == bcm_field_group_status_get(unit, *p_group_id, &fg_status))
+ {
+ bcm_field_group_config_t_init(&grp);
+
+ BCM_FIELD_QSET_INIT(grp.qset);
+ /* TCAM entry limit to 80 bits per slice, but up to 4 slices for a group
+ use ModeAuto to automatically adjust it */
+
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyInVPort); /* 32 bits */
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyPacketRes);
+
+ BCM_FIELD_QSET_ADD(grp.qset, bcmFieldQualifyStageIngress);
+
+ BCM_FIELD_ASET_INIT(grp.aset);
+ BCM_FIELD_ASET_ADD(grp.aset, bcmFieldActionDrop);
+
+ grp.priority = 10; /* the higher the number the higher the priority */
+ grp.flags = (BCM_FIELD_GROUP_CREATE_WITH_MODE | BCM_FIELD_GROUP_CREATE_WITH_ASET);
+ grp.mode = bcmFieldGroupModeAuto;
+
+ ret = bcm_field_group_config_create(unit, &grp);
+
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to create default field - %d\n", ret );
+ return BCM_ERR_INTERNAL;
+ }
+
+ *p_group_id = grp.group;
+ BCM_LOG(INFO, log_id_sw_util, "Default Field Group %d created\n", *p_group_id);
+ return BCM_ERR_OK;
+ }
+ return BCM_ERR_ALREADY;
+ }
+
+/**
+ * @brief The acl add function add an Access Control Rule in the switch VCAP/ICAP/ECAP
+ * to perform action based on flow classifier
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_flow a pointer to the flow definition the created rule will be based on
+ * @param p_flow_elm a pointer to the switch internal flow list
+ * @param in_gport ingress virtual port (LIF) this acl applied
+ * @param out_gport egress virtual port (LIF) this acl applied
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_dpp_acl_add(int unit, bcmbal_flow_cfg *p_flow, bal_sw_flow *p_flow_elm, uint32_t in_gport, uint32_t out_gport)
+{
+ int32_t ret = 0;
+ uint16_t udp_port, flow_pri;
+ bcm_field_entry_t eid;
+ bcm_gport_t trap_gport;
+ bcm_mac_t dst_mac, src_mac;
+ bcm_mac_t mac_mask = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ uint32_t trap_code = 0;
+ bcmos_errno err;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Add an ACL to a flow w type = %d\n", p_flow->key.flow_type);
+
+ if(p_flow_elm->num_eid >= MAX_FIELD_EID)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Too many ACL rules in flow id %d\n", p_flow_elm->id);
+ return BCM_ERR_NORES;
+ }
+
+ err = bal_sw_util_dpp_fg_create(unit, &dpp_group_id);
+
+ if (BCM_ERR_ALREADY != err && BCM_ERR_OK != err)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Field Group %d create failed\n", dpp_group_id);
+ return err;
+ }
+
+ /* fill in the match fields */
+ do
+ {
+ ret = bcm_field_entry_create(unit, dpp_group_id, &eid);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_entry_create failed - %d\n", ret);
+ break;
+ }
+ /* if upstream, match ingress port */
+ if(p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM && BCMBAL_CFG_PROP_IS_SET(p_flow, flow, access_int_id))
+ {
+ ret = bcm_field_qualify_InPort(unit, eid, bal_bcm_pon_inf_pbm_get(p_flow->data.access_int_id), 0xffffffff);
+ if (BCM_E_NONE != ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_InPort failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add InPort %d to qualifier\n", bal_bcm_pon_inf_pbm_get(p_flow->data.access_int_id));
+ }
+
+ }
+ /* if downstream, match ingress nni port */
+ if(p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM && BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id))
+ {
+ ret = bcm_field_qualify_InPort(unit, eid, bal_bcm_net_inf_pbm_get(p_flow->data.network_int_id), 0xffffffff);
+ if (BCM_E_NONE != ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_InPort failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add network port %d to qualifier\n", bal_bcm_net_inf_pbm_get(p_flow->data.network_int_id));
+ }
+ }
+ /* match ether type */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ether_type))
+ {
+ ret = bcm_field_qualify_EtherType(unit, eid, p_flow->data.classifier.ether_type, 0xffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_EtherType failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add ether type 0x%x to qualifier\n", p_flow->data.classifier.ether_type );
+ }
+ }
+ /* add IP protocol to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, ip_proto))
+ {
+ ret = bcm_field_qualify_IpProtocol(unit, eid, p_flow->data.classifier.ip_proto, 0xff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_IpProtocol failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add ip protocol 0x%x to qualifier\n", p_flow->data.classifier.ip_proto );
+ }
+ }
+ /* add L3 source port to match rule - Don't be confused by the API name */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_port))
+ {
+ udp_port = p_flow->data.classifier.src_port;
+ ret = bcm_field_qualify_L4SrcPort(unit, eid, udp_port, 0xffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_L4SrcPort failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add src port %d to qualifier\n", udp_port );
+ }
+ }
+ /* add L3 destination port to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_port))
+ {
+ udp_port = p_flow->data.classifier.dst_port;
+ ret = bcm_field_qualify_L4DstPort(unit, eid, udp_port, 0xffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_L4DstPort failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add dst port %d to qualifier\n", udp_port );
+ }
+ }
+ /* add Outer vid to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid))
+ {
+ ret = bcm_field_qualify_OuterVlanId(unit, eid, p_flow->data.classifier.o_vid, 0x0fff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_OuterVlanId failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add outer vid 0x%x to qualifier\n", p_flow->data.classifier.o_vid );
+ }
+ }
+ /* add Inner vid to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid))
+ {
+ ret = bcm_field_qualify_InnerVlanId(unit, eid, p_flow->data.classifier.i_vid, 0x0fff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_InnerVlanId failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add Inner vid 0x%x to qualifier\n", p_flow->data.classifier.i_vid );
+ }
+ }
+ /* add Outer priority to match rule - only accept 3 bits */
+ /* use ACL for downstream, upstream pbit classification will be done through PON LIF */
+ if(p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM &&
+ BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_pbits))
+ {
+ ret = bcm_field_qualify_OuterVlanPri(unit, eid, p_flow->data.classifier.o_pbits, 0x7);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_OuterVlanPri failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add outer pri 0x%x to qualifier\n", p_flow->data.classifier.o_pbits );
+ }
+ }
+ /* add Inner priority to match rule - only accept 3 bits */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_pbits))
+ {
+ ret = bcm_field_qualify_InnerVlanPri(unit, eid, p_flow->data.classifier.i_pbits, 0x7);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_InnerVlanPri failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add inner pri 0x%x to qualifier\n", p_flow->data.classifier.i_pbits );
+ }
+ }
+ /* add Dst Mac to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac))
+ {
+ memcpy(&dst_mac, &(p_flow->data.classifier.dst_mac), sizeof(bcm_mac_t));
+ ret = bcm_field_qualify_DstMac(unit, eid, dst_mac, mac_mask);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_DstMac failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add DstMac %x:%x:%x:%x:%x:%x to qualifier\n",
+ p_flow->data.classifier.dst_mac.u8[0],
+ p_flow->data.classifier.dst_mac.u8[1],
+ p_flow->data.classifier.dst_mac.u8[2],
+ p_flow->data.classifier.dst_mac.u8[3],
+ p_flow->data.classifier.dst_mac.u8[4],
+ p_flow->data.classifier.dst_mac.u8[5] );
+ }
+ }
+ /* add Src Mac to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_mac))
+ {
+ memcpy(&src_mac, &(p_flow->data.classifier.src_mac), sizeof(bcm_mac_t));
+ ret = bcm_field_qualify_SrcMac(unit, eid, src_mac, mac_mask);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_SrcMac failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add SrcMac[5] 0x%x to qualifier\n", p_flow->data.classifier.src_mac.u8[5] );
+ }
+ }
+ /* add Dst IP to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_ip))
+ {
+ ret = bcm_field_qualify_DstIp(unit, eid, p_flow->data.classifier.dst_ip.u32, 0xffffffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_DstIp failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add DstIp 0x%x to qualifier\n", p_flow->data.classifier.dst_ip.u32 );
+ }
+ }
+
+ /* add Src IP to match rule */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_ip))
+ {
+ ret = bcm_field_qualify_SrcIp(unit, eid, p_flow->data.classifier.src_ip.u32, 0xffffffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_SrcIp failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add SrcIp 0x%x to qualifier\n", p_flow->data.classifier.src_ip.u32 );
+ }
+ }
+ /* set ACL priority */
+ if(BCMBAL_CFG_PROP_IS_SET(p_flow, flow, priority))
+ {
+ flow_pri = p_flow->data.priority;
+ }
+ else /* default to 10, valid range 0 - 65535 */
+ {
+ flow_pri = BAL_FLOW_DEFAULT_PRIORITY;
+ /* set the presence of priority bit in the flow to reflect insertion of DEFAULT_PRIORITY */
+ BCMBAL_CFG_PROP_SET(p_flow, flow, priority, flow_pri);
+ }
+ ret = bcm_field_entry_prio_set(unit, eid, flow_pri);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field entry priority failed - %d\n", ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "field entry priority set to - %d\n", flow_pri);
+ }
+
+ }while(0);
+
+ if (BCM_E_NONE == ret) /* make sure the field qualifier settings are good */
+ {
+ if( BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action) &&
+ BCMBAL_ACTION_CMD_ID_IS_SET( &(p_flow->data.action), BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST) )
+ {
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a flow action cmd=0x%x \n", p_flow->data.action.cmds_bitmask);
+ do
+ {
+ ret = bal_sw_util_create_trap_gport(unit, &trap_gport, &trap_code);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "create_trap_gport failed - %d\n", ret);
+ break;
+ }
+ /* qualify with in LIF */
+ if(in_gport)
+ {
+ /* add vPort to match rule */
+ ret = bcm_field_qualify_InVPort32(unit, eid, in_gport, 0xffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_InVPort failed - %d\n", ret);
+ break;
+ }
+ }
+ ret = bcm_field_action_add(unit, eid, bcmFieldActionTrap, trap_gport, 0);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field action add failed - %d\n", ret);
+ break;
+ };
+ ret = bcm_field_entry_install(unit, eid);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_entry_install %d failed - %d\n", eid, ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add rule %d Success\n", eid);
+ }
+
+ }while(0);
+ }
+ /* regular forwarding ACL */
+ else
+ {
+ do
+ {
+ /* redirect to the egress LIF */
+ ret = bcm_field_action_add(unit, eid, bcmFieldActionRedirect, 0, out_gport);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field action add failed - %d\n", ret);
+ break;
+ };
+ /* trigger vlan translation at the egress LIF */
+ ret = bcm_field_action_add(unit, eid, bcmFieldActionVportNew, out_gport, 0);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field action add new vport failed - %d\n", ret);
+ break;
+ };
+
+ ret = bcm_field_entry_install(unit, eid);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_entry_install %d failed - %d\n", eid, ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add rule %d to gport 0x%x Success\n", eid, out_gport);
+ }
+ }while(0);
+ }
+ }
+
+ if (ret != BCM_E_NONE)
+ {
+ /* TBD - release the eid and trap port resource */
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ /* add flow info into the internal link list */
+ p_flow_elm->trap_code = trap_code;
+ p_flow_elm->trap_port = trap_gport;
+ p_flow_elm->field_entry_id[p_flow_elm->num_eid] = eid;
+ p_flow_elm->num_eid += 1;
+ p_flow_elm->valid = 1;
+ return BCM_ERR_OK;
+ }
+}
+
+/**
+ * @brief The default acl add function add a DROP Access Control Rule on the ingress LIF
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_flow a pointer to the flow definition the created rule will be based on
+ * @param p_flow_elm a pointer to the switch internal flow list
+ * @param in_gport ingress virtual port (LIF) this acl applied
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_dpp_dft_acl_add(int unit, bcmbal_flow_cfg *p_flow, bal_sw_flow *p_flow_elm, uint32_t in_gport)
+{
+ bcmos_errno err;
+ bcm_field_entry_t dft_eid = 0;
+ int32_t ret = 0;
+
+ if(p_flow_elm->num_eid >= MAX_FIELD_EID)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Too many dft ACL rules in flow id %d\n", p_flow_elm->id);
+ return BCM_ERR_NORES;
+ }
+
+ err = bal_sw_util_dpp_dft_fg_create(unit, &dpp_group_id);
+
+ if (BCM_ERR_ALREADY != err && BCM_ERR_OK != err)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Field Default Group %d create failed\n", dpp_dft_group_id);
+ return err;
+ }
+ do
+ {
+ /* Install a default drop ACL at lowest priority(0).
+ This will drop unmatch packets received on the same ingress LIF
+ */
+
+ ret = bcm_field_entry_create(unit, dpp_group_id, &dft_eid);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_entry_create failed - %d\n", ret);
+ break;
+ }
+
+ /* add vPort to match rule */
+ ret = bcm_field_qualify_InVPort32(unit, dft_eid, in_gport, 0xffff);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_InVPort failed - %d\n", ret);
+ break;
+ }
+
+ /* add Packet type to match rule, drop only unicast */
+ ret = bcm_field_qualify_PacketRes(unit, dft_eid, BCM_FIELD_PKT_RES_L2UC, 0);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_qualify_PacketRes failed - %d\n", ret);
+ break;
+ }
+
+
+ /* set to lowest priority 0 */
+ ret = bcm_field_entry_prio_set(unit, dft_eid, 0);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field entry priority failed - %d\n", ret);
+ break;
+ };
+
+ /* Drop the packet */
+ ret = bcm_field_action_add(unit, dft_eid, bcmFieldActionDrop, 0, 0);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field action add failed - %d\n", ret);
+ break;
+ };
+ ret = bcm_field_entry_install(unit, dft_eid);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "field_entry_install %d failed - %d\n", dft_eid, ret);
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Add default rule %d Success\n", dft_eid);
+ }
+ }while(0);
+ if (ret != BCM_E_NONE)
+ {
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ p_flow_elm->field_entry_id[p_flow_elm->num_eid] = dft_eid;
+ p_flow_elm->num_eid += 1;
+ return BCM_ERR_OK;
+ }
+}
+
+/**
+ * @brief The ingress vlan translation function modified the packet VLAN tag
+ * before sending it out
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_flow a pointer to the flow definition the created rule will be based on
+ * @param ingport the gport the translation will be applied
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_dpp_invlanx(int unit, bcmbal_flow_cfg *p_flow, uint32_t ingport)
+{
+ int rv = 0;
+ bcm_vlan_action_set_t action;
+ bcm_vlan_action_set_t_init(&action);
+ bcmos_errno ret;
+
+ if(BCMBAL_ACTION_CMD_ID_IS_SET( &(p_flow->data.action), BCMBAL_ACTION_CMD_ID_REMARK_PBITS))
+ {
+ int qos_map_id, i_pri, o_pri;
+
+ do
+ {
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ /* should be
+ action.dt_outer_pkt_prio = bcmVlanActionReplace;
+ action.new_outer_vlan = p_flow->data.classifier.o_vid;;
+ action.dt_outer = bcmVlanActionReplace;
+ but it does not seems to work. Using ot_outer seems to also work for double tagged packets
+ */
+ action.ot_outer_pkt_prio = bcmVlanActionReplace;
+ action.new_outer_vlan = p_flow->data.classifier.o_vid;
+ action.ot_outer = bcmVlanActionReplace;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ action.ot_outer_pkt_prio = bcmVlanActionReplace;
+ action.new_outer_vlan = p_flow->data.classifier.o_vid;
+ action.ot_outer = bcmVlanActionReplace;
+
+ break;
+ default:
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Error, pbits translation on untagged packets\n");
+ return BCM_ERR_NOT_SUPPORTED;
+ break;
+ }
+
+
+ /* perform o_pbits translation */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_pbits))
+ {
+ i_pri = p_flow->data.classifier.o_pbits;
+ }
+ else
+ {
+ /* mark the source pcp DONTCARE */
+ i_pri = -1;
+ }
+ /* flow validation already make sure the action.o_pbits is set for REMARK_PBITS */
+ o_pri = p_flow->data.action.o_pbits;
+
+ ret = bal_sw_dpp_pcp_remark_map_get(i_pri, o_pri, &qos_map_id);
+
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Error, faile to obtain pcp map id, ret = %d\n", ret);
+ rv = BCM_E_UNAVAIL;
+ break;
+ }
+
+ rv = bcm_qos_port_map_set(unit, ingport, qos_map_id, -1);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Error, pbits translation bcm_qos_port_map_set ret = %d\n", rv);
+ break;
+ }
+
+ /* set the action priority profile */
+ action.priority = qos_map_id;
+ action.new_inner_pkt_prio = qos_map_id;
+ }while(0);
+ }
+ else
+ {
+ /* nothing to do, return OK */
+ return BCM_ERR_OK;
+ }
+ if(rv != BCM_E_NONE)
+ {
+ return BCM_ERR_INTERNAL;
+ }
+
+ rv = bcm_vlan_translate_action_create(unit, ingport, bcmVlanTranslateKeyPortOuter, BCM_VLAN_INVALID, BCM_VLAN_NONE, &action);
+ if( rv )
+ {
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Perform ingress vlan translation w %s action on gport 0x%x\n",
+ (p_flow->data.classifier.pkt_tag_type == BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG)? "DT": "ST",
+ ingport);
+ return BCM_ERR_OK;
+ }
+}
+/**
+ * @brief The egress vlan translation function modified the packet VLAN tag
+ * before sending it out
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_flow a pointer to the flow definition the created rule will be based on
+ * @param egport the gport the translation will be applied
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_dpp_evlanx(int unit, bcmbal_flow_cfg *p_flow, uint32_t egport)
+{
+ int rv = 0;
+ bcm_vlan_action_set_t action;
+ bcm_vlan_action_set_t_init(&action);
+
+ if(BCMBAL_ACTION_CMD_ID_IS_SET( &(p_flow->data.action), BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG))
+ {
+ action.new_outer_vlan = p_flow->data.action.o_vid;
+ action.priority = 0;
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ action.ut_outer = bcmVlanActionAdd;
+ action.ut_outer_pkt_prio = bcmVlanActionAdd;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ action.ot_outer = bcmVlanActionAdd;
+ action.ot_outer_pkt_prio = bcmVlanActionAdd;
+ break;
+ default:
+ action.new_outer_vlan = 0;
+ action.ot_outer = bcmVlanActionNone;
+ break;
+ }
+
+ if( p_flow->data.action.o_tpid )
+ {
+ action.outer_tpid_action = bcmVlanTpidActionModify;
+ action.outer_tpid = p_flow->data.action.o_tpid;
+ }
+
+ }
+ else if(BCMBAL_ACTION_CMD_ID_IS_SET( &(p_flow->data.action), BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG))
+ {
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ /* should be action.dt_outer = bcmVlanActionDelete,
+ but it does not seems to work. Using ot_outer seems to also work for double tagged packets */
+ action.ot_outer = bcmVlanActionDelete;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ action.ot_outer = bcmVlanActionDelete;
+ break;
+ default:
+ action.ut_outer = bcmVlanActionNone;
+ break;
+ }
+ }
+ else if (BCMBAL_ACTION_CMD_ID_IS_SET( &(p_flow->data.action), BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG))
+ {
+ action.new_outer_vlan = p_flow->data.action.o_vid;
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ /* should be action.dt_outer = bcmVlanActionReplace,
+ but it does not seems to work. Using ot_outer seems to also work for double tagged packets */
+ action.ot_outer = bcmVlanActionReplace;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ action.ot_outer = bcmVlanActionReplace;
+ break;
+ default:
+ action.ut_outer = bcmVlanActionNone;
+ break;
+ }
+
+ /** @todo tpid is not translated for now */
+ /** @note the vid translated from is passed as a parameter to the api call */
+
+ }
+ else
+ {
+ /* nothing to do, return OK */
+ return BCM_ERR_OK;
+ }
+
+ rv = bcm_vlan_translate_egress_action_add(unit, egport, BCM_VLAN_NONE, BCM_VLAN_NONE, &action);
+ if( rv )
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "bcm_vlan_translate_egress_action_add failed %d on gport 0x%x\n", rv, egport);
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Perform egress vlan translation on gport 0x%x\n", egport);
+ return BCM_ERR_OK;
+ }
+}
+/**
+ * @brief Multicast flow add function forward the specified multicast packets to a multicast group.
+ * The multicast group has to be created prio to the mc_flow add operation
+ *
+ * @param p_flow a pointer to the flow definition the created rule will be based on
+ * @param service_type id this multicast flow is for multicast or downstream N:1 service
+ * @return error code
+ */
+static bcmos_errno bal_sw_util_dpp_mc_flow_add(bcmbal_flow_cfg *p_flow, uint32_t service_type)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcm_gport_t nni_gport;
+ int ii, unit, rv;
+ int nni;
+ bcm_vlan_t vsi;
+ bal_sw_flow *p_flow_elm;
+ bal_sw_flow flow_elm;
+ bal_sw_vsi_service *p_vsi_svc;
+ bal_sw_group_list *p_group_list;
+ uint32_t svc_tag_indx;
+
+ /* get a pointer to the specified group instance */
+ p_group_list = bal_sw_util_dpp_group_list_get_by_id(p_flow->data.group_id);
+
+ if ( p_group_list == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: group %d not found\n", p_flow->data.group_id);
+ return BCM_ERR_INTERNAL;
+ }
+
+ unit = p_group_list->device;
+
+ /* make sure this flow id does not already exist */
+ p_flow_elm = bal_sw_util_flow_list_get_by_id(p_flow->key.flow_id);
+ if (p_flow_elm)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: flow id %d type %d already exist\n",p_flow->key.flow_id, p_flow->key.flow_type);
+ return BCM_ERR_INTERNAL;
+ }
+
+ do
+ {
+ /* initialize link list flow element */
+ memset(&flow_elm, 0, sizeof (bal_sw_flow));
+ /* fill in the basic info */
+ flow_elm.id = p_flow->key.flow_id;
+ flow_elm.device = unit;
+ flow_elm.group_id = p_flow->data.group_id;
+ flow_elm.flow_cookie = p_flow->data.cookie;
+
+ /* packet tag type are required fields when create NNI LIF */
+ /* Here make sure it is the supported type */
+ if(p_flow->data.classifier.pkt_tag_type != BCMBAL_PKT_TAG_TYPE_UNTAGGED &&
+ p_flow->data.classifier.pkt_tag_type != BCMBAL_PKT_TAG_TYPE_SINGLE_TAG &&
+ p_flow->data.classifier.pkt_tag_type != BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: MC classifier packet tag type 0x%x is invalid\n", p_flow->data.classifier.pkt_tag_type);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /* retrieve the vswitch instance */
+ p_vsi_svc = p_group_list->p_vsi;
+ if(p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, MC: vsi not created\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ vsi = p_vsi_svc->vswitch;
+
+ /* add flow to the vsi service tag list */
+ ret = bal_sw_util_dpp_vsi_service_tag_add(unit, p_vsi_svc, p_flow, &svc_tag_indx);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add flow to vsi service tag list\n");
+ break;
+ }
+
+ ii = 0; /* Start with the first NNI logical interface */
+ /* loop through all nni port, add them to vswitch, -1 indicate end of table */
+ /* Configure the switch nni LIF based on classifier in the flow. */
+ while(-1 != (nni = bal_bcm_net_inf_pbm_get(ii)))
+ {
+ /* skip nni port that is not in the same device or not valid */
+ if ( bal_bcm_net_inf_dev_get(ii) != unit ||
+ BCMOS_FALSE == bcm_topo_nni_is_valid(ii))
+ {
+ ii++;
+ continue;
+ }
+
+ /* if nni port is specified in the flow, skip the other nni ports */
+ if ( BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id) &&
+ ii != p_flow->data.network_int_id
+ )
+ {
+ ii++;
+ continue;
+ }
+
+ /* create gport based on nni physical port number */
+ ret = bal_sw_util_dpp_vsi_service_port_add(unit, p_vsi_svc, svc_tag_indx, nni, &nni_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add nni %d to vsi\n", nni);
+ break;
+ }
+
+ /* if DMAC is set, create a L2 entry, otherwise flood unknown to the group */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac))
+ {
+ /* add static MC 01:00:5E:00:00:start_mc to the dowstream MC group */
+ bcm_l2_addr_t l2addr;
+ bcm_mac_t mc_mac;
+
+ /* Add mc mac address */
+ memcpy(&mc_mac, &(p_flow->data.classifier.dst_mac), sizeof(bcm_mac_t));
+
+ bcm_l2_addr_t_init(&l2addr, mc_mac, vsi);
+ l2addr.flags = BCM_L2_STATIC | BCM_L2_MCAST;
+ /* direct output to the MC group */
+ l2addr.l2mc_group = p_group_list->l2_grp_id;
+
+ rv = bcm_l2_addr_add(unit, &l2addr);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,"Error: bcm_l2_addr_add MC returned %s \n",
+ bcm_errmsg(rv));
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ else
+ {
+ rv = bcm_port_control_set(unit, nni_gport, bcmPortControlFloodUnknownMcastGroup, BAL_DPP_MC_OFFSET);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, MC: bcm_port_control_set for nni failed %d\n", rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ flow_elm.num_net++;
+ flow_elm.net_port[ii] = nni_gport;
+
+ ii++; /* Next NNI */
+ }
+ /* skip the rest if anything goes wrong */
+ if( ret != BCM_ERR_OK)
+ {
+ break;
+ }
+ /* perform vlan translation on nni port */
+ if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action))
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "Warning, action for multicast flow not supported\n");
+ }
+
+ } while(0);
+
+ if( ret == BCM_ERR_OK)
+ {
+ /* increase the group reference count */
+ p_group_list->use_count++;
+ /* increase the vsi reference count */
+ p_vsi_svc->use_count++;
+ /* add the flow info to the flow link list */
+ flow_elm.p_vsi_svc = p_vsi_svc;
+ flow_elm.num_pon = 0;
+ flow_elm.type = service_type;
+ /* nni ports are done in the nni loop */
+ flow_elm.valid = 1;
+ bal_sw_util_flow_list_insert(flow_elm);
+
+ BCM_LOG(INFO, log_id_sw_util, "Add flow_elm %d type %d, vswitch 0x%x, group_id %d Success\n", flow_elm.id, flow_elm.type, p_vsi_svc->vswitch, flow_elm.group_id);
+ }
+ return ret;
+}
+
+/* HW limitation on max burst rate - bps */
+#define BAL_MAX_BURST_RATE (1 << 16)
+
+/**
+ * @brief The flow add function program DPP to forward packets that have
+ * specified attributes to the designated ports.
+ * The packets is modified before egress
+ * In case IWF is in DIRECT MODE,
+ * On the downstream, a tunnel id (outer vlan tag) is added to the packets
+ * On the upstream, outer vlan tag (tunnel id) is removed from the packets
+ * In case IWF is in PER_FLOW_MODE, currently not supported
+ *
+ * @note a flow can be created which does VID translation between V & U (refer to TR156) interfaces.
+ *
+ * @note This routine adds flow for both upstream and downstream direction i.e. create PON & NNI LIFs
+ * for both directions in a same call to this routine - and all this as part of a single call to this function
+ * from the application module or CLI.
+ * It also programs the egress vlan translation modules for both upstream and downstream.
+ *
+ * @note The general sequence is:
+ * \li create PON LIF with matching ingress tunnel id (and vlan id, if upstream pkts are vlan tagged)
+ * \li next, configure egress vlan translation on PON side (for downstream pkts)
+ * \li create NNI LIF with matching ingress vlan id (currently by default it assumes downstream packets are tagged)
+ * \li next, configure egress vlan translation on NNI side (for upstream pkts)
+ *
+ * @param iwf_mode The InterWorking Function mode - DIRECT or PER-FLOW
+ * @param p_flow A pointer to the requested add flow info
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_flow_add(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcm_gport_t pon_gport, nni_gport;
+ bcm_vlan_t tunnel_id;
+ int ii, unit, rv;
+ bcm_vlan_port_t vp;
+ int pon, nni, sys_pon;
+ bcm_vlan_t vsi;
+ int pon_encap_id;
+ bal_sw_flow *p_flow_elm;
+ uint32_t flow_type, max_burst, svc_tag_indx;
+ bal_sw_flow flow_elm;
+ bal_sw_dpp_qos_service_cfg *p_service_cfg = NULL;
+ bcmbal_flow_cfg flow_rev; /* used for configuration in opposite direction */
+ bcmbal_flow_cfg *p_us_flow, *p_ds_flow;
+ bal_sw_vsi_service *p_vsi_svc;
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got an DPP flow request - iwf_mode=%d flow_id=%d flow_type=%d, sub_port=%d svc_id=%d\n",
+ iwf_mode,
+ p_flow->key.flow_id, p_flow->key.flow_type, p_flow->data.access_int_id, p_flow->data.svc_port_id);
+ BCM_LOG(DEBUG, log_id_sw_util,
+ " classifier - mask=0x%x otpid=%x itpid=%x ovid=%x ivid=%x\n",
+ p_flow->data.classifier.presence_mask,
+ p_flow->data.classifier.o_tpid, p_flow->data.classifier.i_tpid,
+ p_flow->data.classifier.o_vid, p_flow->data.classifier.i_vid);
+
+
+ if ( iwf_mode != BCMBAL_IWF_MODE_DIRECT_MAPPING)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: not supported IWF mode - %d\n", iwf_mode);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action))
+ {
+ BCM_LOG(DEBUG, log_id_sw_util,
+ " action.params: .cmds_bitmask=0x%x, .input_pkt_tag_type=0x%x\n",
+ p_flow->data.action.cmds_bitmask,
+ p_flow->data.classifier.pkt_tag_type);
+ }
+
+ if (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM &&
+ BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, sla) &&
+ p_flow->data.sla.max_rate < p_flow->data.sla.min_rate)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: Max rate %d kbps is not >= Min rate %d kbps\n", p_flow->data.sla.max_rate, p_flow->data.sla.min_rate );
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ switch(p_flow->key.flow_type)
+ {
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ flow_type = BAL_SW_FLOW_TYPE_DOWNSTREAM;
+ /* for downstream N:1 service, same flood settings as multicast flow */
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id))
+ {
+ return bal_sw_util_dpp_mc_flow_add(p_flow, BAL_SW_FLOW_TYPE_DOWNSTREAM);
+ }
+ break;
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ flow_type = BAL_SW_FLOW_TYPE_UPSTREAM;
+ break;
+ case BCMBAL_FLOW_TYPE_MULTICAST:
+ return bal_sw_util_dpp_mc_flow_add(p_flow, BCMBAL_FLOW_TYPE_MULTICAST);
+ default:
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ unit = bal_bcm_pon_inf_dev_get(p_flow->data.access_int_id);
+ /* We program a flow with 3 switch components, inLIF, vSwitch and outLIF.
+ LIF is always bi-directional operation, so for uni-directional flow we programmed an ingress or egress DROP
+ on PON based on the BAL flow direction. Later, when the BAL flow from the other direction is SET, we
+ remove the DROP from the PON.
+ This imply that two BAL flows with same id must have symmetry vlan manipulation operations.
+ */
+ p_flow_elm = bal_sw_util_flow_list_get_by_id(p_flow->key.flow_id);
+ if (p_flow_elm)
+ {
+ /* Check if flow with same id and type exist or not.
+ If downstream exist, remove the DISCARD_INGRESS from PON port by set it to DISCARD_NONE.
+ If upstream exist, remove the DISCARD_EGRESS from PON port by set it to DISCARD_NONE.
+ Asymmetry operations need two flows with different ID - each flow in uni-direction */
+ if(!(p_flow_elm->type & flow_type))
+ {
+ bcmbal_flow_cfg *p_ref_flow = NULL;
+ bcmbal_flow_key key;
+ /* retrieve the classifier on the other flow direction */
+ key.flow_id = p_flow->key.flow_id;
+ key.flow_type = (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM)? BCMBAL_FLOW_TYPE_UPSTREAM : BCMBAL_FLOW_TYPE_DOWNSTREAM;
+ p_ref_flow = flow_get_current_info_by_key(key);
+ if(NULL == p_ref_flow)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: Can't locate flow %d type %d info from main DB\n", key.flow_id, key.flow_type);
+ return BCM_ERR_INTERNAL;
+ }
+ /* check the symmetrical properties between two flows */
+ if (BCMOS_FALSE == bal_sw_util_is_symmetry_flows(p_flow, p_ref_flow))
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: Flow %d does not have symmetry classifiers\n", key.flow_id);
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* if there is SLA in downstream, remove the US flow ( LIFs & VSWITCH) and build a new bi-direction flow.
+ This is because LIF is always bi-directional and when the US flow is created the PON LIF has no downstream VOQ.
+ One needs to create a new PON LIF with VOQ for SLA. There is no easy way to add VOQ to an existing LIF. */
+ if( p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM &&
+ BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, sla) )
+ {
+ /* remove the existing US flow */
+ ret = bal_sw_util_dpp_flow_remove_int(p_flow_elm);
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: fail to remove flow %d from the list\n", p_flow->key.flow_id);
+
+ return BCM_ERR_INTERNAL;
+ }
+ flow_type = BAL_SW_FLOW_TYPE_DOWNSTREAM | BAL_SW_FLOW_TYPE_UPSTREAM;
+ /* goto regular path to create bi-directional flow */
+ }
+ /* if no SLA and the classifier is more than just port + VLAN tags, add ACL rule to re-direct packet to egress port.
+ This bypass the ingress LIF as LIF check VID only.
+ Upstream classification is expected to be done in ONU (onu add GEM based on classifiers for upstream),
+ return success after complete as there is no other changes needed for existing flow.
+ */
+ else
+ {
+ int i;
+ bcmos_bool is_nni_set = BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id);
+
+ if( p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM &&
+ bal_sw_util_flow_ds_acl_cls_chk(p_flow) == BCMOS_TRUE )
+ {
+ for(i=0; i < p_flow_elm->num_pon; i++)
+ {
+ for(ii=0; ii < p_flow_elm->num_net; ii++)
+ {
+ /*first get the ING logical port from gport */
+ bcm_vlan_port_t tmp_vp;
+ bcm_vlan_port_t_init(&tmp_vp);
+ tmp_vp.vlan_port_id = p_flow_elm->net_port[ii];
+ ret = bcm_vlan_port_find(unit, &tmp_vp);
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(WARNING, log_id_sw_util,
+ " Warning: fail to retrieve logical port from gport 0x%x\n", p_flow_elm->net_port[ii]);
+ continue;
+ }
+ /* if nni port is specified in the flow, skip the other nni ports */
+ if ( BCMOS_TRUE == is_nni_set && tmp_vp.port != bal_bcm_net_inf_pbm_get(p_flow->data.network_int_id))
+ {
+ ii++;
+ /* if nni is set, it has to be in the nni list of the opposit FLOW */
+ /* set the return to BCM_ERR_INTERNAL, in case it reach the end of for-loop. */
+ ret = BCM_ERR_INTERNAL;
+ continue;
+ }
+ /* Rule need to match the ingress port, otherwise, it will apply to all ports - nni and pon */
+ if ( BCMOS_TRUE != is_nni_set)
+ {
+ BCMBAL_CFG_PROP_SET(p_flow, flow, network_int_id, bal_bcm_net_inf_idx_get(tmp_vp.port));
+ }
+ ret = bal_sw_util_dpp_acl_add(unit, p_flow, p_flow_elm, p_flow_elm->net_port[ii], p_flow_elm->pon_port[i]);
+ if ( BCMOS_TRUE != is_nni_set)
+ {
+ BCMBAL_CFG_PROP_CLEAR(p_flow, flow, network_int_id);
+ }
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add forwarding acl on nni %d, ret = %d\n", ret, ii);
+ break;
+ }
+ /* add a dft drop rule (priority 0) on the LIF to drop packets that match VID but no match for other fields */
+ ret = bal_sw_util_dpp_dft_acl_add(unit, p_flow, p_flow_elm, p_flow_elm->net_port[ii]);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add default acl on nni=0x%x, ret = %d\n", p_flow_elm->net_port[ii], ret);
+ break;
+ }
+ }
+ if (ret != BCM_ERR_OK)
+ {
+ break;
+ }
+ }
+
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: fail to add DS ACL to nni_%d in flow id %d from the list\n", ii,p_flow->key.flow_id);
+
+ return BCM_ERR_INTERNAL;
+ }
+ }
+ /* If the US and DS has asymmetrical nature, we only program common part (VID) when create the LIF
+ We need an ACL rule to perform upstream specific classification and forwarding.
+ In addition, ACL allow upstream flows to be prioritized based on priority field.*/
+ if( p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM &&
+ bal_sw_util_flow_us_acl_cls_chk(p_flow) == BCMOS_TRUE &&
+ /* there are issues using traditional API for PON application when egress vlan translation and ingress ACL are both active.
+ Enable the ACL only when there is no vlan action - TBD */
+ BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action))
+ {
+ if ( BCMOS_FALSE == is_nni_set)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: Upstream classifier in addition to VID without setting NNI is not supported\n");
+ return BCM_ERR_INTERNAL;
+ }
+
+ for(i=0; i < p_flow_elm->num_pon; i++)
+ {
+ ret = bal_sw_util_dpp_acl_add(unit, p_flow, p_flow_elm, p_flow_elm->pon_port[i], p_flow_elm->net_port[p_flow->data.network_int_id]);
+
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add forwarding acl on pon %d, ret = %d\n", ret, i);
+ break;
+ }
+ /* add a default drop rule (priority 0) on the LIF to drop packets that match VID but no match for other fields */
+ ret = bal_sw_util_dpp_dft_acl_add(unit, p_flow, p_flow_elm, p_flow_elm->pon_port[i]);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add default acl on pon=0x%x, ret = %d\n", p_flow_elm->pon_port[i], ret);
+ break;
+ }
+ }
+
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: fail to add US ACL to pon_%d in flow id %d from the list\n", i, p_flow->key.flow_id);
+ return BCM_ERR_INTERNAL;
+ }
+ }
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " remove packet discard function from PON in flow id %d \n",p_flow->key.flow_id);
+ /* remove the PON ports from DISCARD_XXX mode */
+ for(ii=0; ii<p_flow_elm->num_pon; ii++)
+ {
+ if(p_flow_elm->pon_port[ii] == 0)
+ {
+ /* if PON LIF is deleted, then continue to the next one */
+ continue;
+ }
+ ret = bcm_port_discard_set(p_flow_elm->device, p_flow_elm->pon_port[ii], BCM_PORT_DISCARD_NONE);
+ if (ret != BCM_ERR_OK)
+ {
+ break;
+ }
+ }
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: fail to remove packet discard from pon_%d in flow id %d from the list\n", ii,p_flow->key.flow_id);
+
+ ret = BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ /* add flow type to the exist list */
+ p_flow_elm->type |= flow_type;
+ ret = BCM_ERR_OK;
+ }
+ return ret;
+ }
+ }
+ else /* same id and type is an error - we do not check if contents are the same or not */
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: flow id %d type %d already exist\n",p_flow->key.flow_id, p_flow->key.flow_type);
+ return BCM_ERR_INTERNAL;
+ }
+ }
+
+ /*
+ * First, validate that the specified PON has at least one NNI port on the same device.
+ * If not, return an error, as this is not supported.
+ */
+ ii = 0;
+ ret = BCM_ERR_NOT_SUPPORTED;
+ /* walk through the entire mapping table */
+ while(-1 != bal_bcm_net_inf_pbm_get(ii))
+ {
+ if(bal_bcm_net_inf_dev_get(ii) == unit)
+ {
+ ret = BCM_ERR_OK;
+ break;
+ }
+ ii++; /* Next NNI */
+ }
+
+ do
+ {
+ /*
+ * Check return code from device check above. Return if there was no local PON .
+ */
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: no network port is on the same device as access port %d\n", p_flow->data.access_int_id);
+ break;
+ }
+
+ /* initialize link list flow element */
+ memset(&flow_elm, 0, sizeof (bal_sw_flow));
+ /* fill in the basic info */
+ flow_elm.id = p_flow->key.flow_id;
+ flow_elm.device = unit;
+ flow_elm.type = flow_type;
+ flow_elm.svc_port = p_flow->data.svc_port_id;
+ flow_elm.flow_cookie = p_flow->data.cookie;
+
+ tunnel_id = (bcm_vlan_t)p_flow->data.svc_port_id;
+ pon = bal_bcm_pon_inf_pbm_get(p_flow->data.access_int_id);
+
+ /* Map the tunnel ID to a PON channel OTM port */
+ rv = bcm_port_pon_tunnel_map_set(unit,
+ pon,
+ tunnel_id,
+ pon);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Error, bcm_port_pon_tunnel_map_set on pon %d failed %d"
+ " (have you chosen the correct intf_maptable?)\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* For TRAP to HOST action, it can be either upstream or downsteram,
+ There is no packet manipulation, just insert an ACL and return.
+ For flow action equal TRAP_TO_HOST, DS flow has to use different flow id even if the classifier is the same as the US.
+ This is to simplify the REMOVE/DELETE operation in the switch.
+ */
+ if ((BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)) &&
+ (p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)
+ )
+ {
+ /* For US, create an in LIF for matching, this allow trapping of different tunnel_id on the same PON.
+ Tunnel_id is stripped before packets are forwarding to the host */
+ if(p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ {
+ if(BCMOS_FALSE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow->data.classifier, classifier, pkt_tag_type, BCMBAL_PKT_TAG_TYPE_UNTAGGED);
+ BCM_LOG(WARNING, log_id_sw_util, "Tag Type for Upstream Packet Trapping is not set, default to UNTAGGED\n");
+ }
+
+ bcm_vlan_port_t_init(&vp);
+
+ /* preserve any incoming packet vlan tags */
+ vp.flags = BCM_VLAN_PORT_OUTER_VLAN_PRESERVE | BCM_VLAN_PORT_INNER_VLAN_PRESERVE | BCM_VLAN_PORT_FORWARD_GROUP;
+
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ /* match both tunnel and outer tag on ingress PON */
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL_VLAN;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ /* match tunnel and both outer and inner tags on ingress PON */
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL_VLAN_STACKED;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ default: /* just to make compiler happy */
+ /* match tunnel tag on ingress PON */
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL;
+ break;
+ }
+
+ vp.port = pon;
+ vp.match_tunnel_value = tunnel_id;
+ vp.egress_tunnel_value = tunnel_id;
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid))
+ {
+ vp.match_vlan = p_flow->data.classifier.o_vid;
+ }
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid))
+ {
+ vp.match_inner_vlan = p_flow->data.classifier.i_vid;
+ }
+ vp.vsi = 0; /* will be populated when the gport is added to service, using vswitch_port_add */
+
+ /* Create the vlan port (i.e., PON LIF) */
+ rv = bcm_vlan_port_create(unit, &vp);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_vlan_port_create pon %d failed %d\n", pon, rv);
+ return BCM_ERR_INTERNAL;
+ }
+ ret = bal_sw_util_dpp_acl_add(unit, p_flow, &flow_elm, vp.vlan_port_id, 0);
+ }
+ else
+ {
+ ret = bal_sw_util_dpp_acl_add(unit, p_flow, &flow_elm, 0, 0);
+ }
+
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " ERROR: fail to add %s acl rule on trap\n", (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)? "US":"DS" );
+ }
+ else
+ {
+ ret = bal_sw_util_flow_list_insert(flow_elm);
+ BCM_LOG(INFO, log_id_sw_util, "Add flow_elm %d type %d, trap_code 0x%x, eid=%d Success\n", flow_elm.id, flow_elm.type, flow_elm.trap_code, flow_elm.field_entry_id[0]);
+ }
+ return ret;
+ } /* endif TRAP_TO_HOST ACTION */
+
+ /* For TR-156 1:1, single tagged on V and R/S interface.
+ The vswitch will push a tunnel tag on the down stream packets.
+ The vswitch will pop the tunnel tag from the upstream packets.
+
+ TBD For TR-156 1:1, double tagged on V interface and single tagged on R/S interface.
+ The vswitch will replace the outer tag with tunnel tag on the down stream packets.
+ The vswitch will replace the tunnel tag with outer vid on upstream packets.
+
+ For TR-156 N:1, single tagged on V and R/S interface.
+ The vswitch will learn the upstream source MAC for downstream forwarding
+ */
+
+ /* packet tag type and service port id are required fields when there is no action - checked in validation stage */
+ /* Here make sure it is the supported type */
+ if(p_flow->data.classifier.pkt_tag_type != BCMBAL_PKT_TAG_TYPE_UNTAGGED &&
+ p_flow->data.classifier.pkt_tag_type != BCMBAL_PKT_TAG_TYPE_SINGLE_TAG &&
+ p_flow->data.classifier.pkt_tag_type != BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: classifier packet tag type 0x%x is invalid\n", p_flow->data.classifier.pkt_tag_type);
+ ret = BCM_ERR_PARM;
+ break;
+ }
+
+ /* create a local reverse flow for symmetry configurations */
+ ret = bal_sw_util_reverse_flow_create(p_flow, &flow_rev);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, (internal failure): fail to reverse flow\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ if(p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ {
+ p_us_flow = p_flow;
+ p_ds_flow = &flow_rev;
+ }
+ else
+ {
+ p_us_flow = &flow_rev;
+ p_ds_flow = p_flow;
+ }
+
+
+ /* create the vswitch */
+ /* if flow is associated with a GROUP, use the vswitch from the GROUP */
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id))
+ {
+ bal_sw_group_list *p_group_list;
+ /* get a pointer to the specified group instance */
+ p_group_list = bal_sw_util_dpp_group_list_get_by_id(p_flow->data.group_id);
+
+ if ( p_group_list == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: group %d not found\n", p_flow->data.group_id);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* retrieve the vswitch instance */
+ p_vsi_svc = p_group_list->p_vsi;
+ vsi = (p_group_list->p_vsi)->vswitch;
+ /* add flow to the vsi service tag list */
+ ret = bal_sw_util_dpp_vsi_service_tag_add(unit, p_vsi_svc, p_flow, &svc_tag_indx);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, flow fail to add service to vsi service tag list\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* set the mac learning distribution list */
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, resolve_mac) &&
+ BCMOS_TRUE == p_flow->data.resolve_mac)
+ {
+ bcm_l2_addr_distribute_t dist;
+
+ bcm_l2_addr_distribute_t_init(&dist);
+ dist.vid = vsi;
+ dist.flags = BCM_L2_ADDR_DIST_SET_CPU_DMA_DISTRIBUTER | BCM_L2_ADDR_DIST_SET_LEARN_DISTRIBUTER;
+ dist.flags |= BCM_L2_ADDR_DIST_LEARN_EVENT | BCM_L2_ADDR_DIST_AGED_OUT_EVENT | BCM_L2_ADDR_DIST_STATION_MOVE_EVENT;
+ rv = bcm_l2_addr_msg_distribute_set(unit, &dist);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_l2_addr_msg_distribute_set");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ }
+ else
+ {
+ /* vsi service needs down stream info for in LIF VLAN info */
+ p_vsi_svc = bal_sw_util_dpp_vsi_service_create(unit, p_ds_flow, &svc_tag_indx);
+ if(p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, vsi create failed\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ vsi = p_vsi_svc->vswitch;
+ }
+ /* === create a PON LIF === */
+
+ /* if DS SLA is set, create a VOQ id, otherwise use local port id */
+ /** @note QoS from the Downstream flow config is taken to configure SLA in the switch. Upstream is done in MAC.
+ */
+ if ((p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM) && (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, sla)))
+ {
+ p_service_cfg = bcmos_calloc(sizeof(bal_sw_dpp_qos_service_cfg));
+ if (p_service_cfg == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to alloc a bal_sw_dpp_qos_service_cfg_t\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ p_service_cfg->service_type = BAL_BCM_SVC_TYPE_IP;
+ p_service_cfg->bal_flow_id = p_flow->key.flow_id;
+ p_service_cfg->pon_port = p_flow->data.access_int_id;
+ p_service_cfg->tunnel_id = tunnel_id;
+ /* TBD - channelize port config */
+ p_service_cfg->ds_qos.pon_chan = 0;
+ p_service_cfg->ds_qos.min.rate = p_flow->data.sla.min_rate;
+ /* burst - set it to twice the rate */
+ max_burst = ( (2*p_service_cfg->ds_qos.min.rate) < BAL_MAX_BURST_RATE )? (2*p_service_cfg->ds_qos.min.rate): BAL_MAX_BURST_RATE;
+ p_service_cfg->ds_qos.min.burst = max_burst;
+ /* TBD priority */
+ p_service_cfg->ds_qos.min.traffic_priority = 2;
+
+ p_service_cfg->ds_qos.max.rate = p_flow->data.sla.max_rate - p_flow->data.sla.min_rate;
+ /* burst - set it to twice the rate */
+ max_burst = ( (2*p_service_cfg->ds_qos.max.rate) < BAL_MAX_BURST_RATE )? (2*p_service_cfg->ds_qos.max.rate): BAL_MAX_BURST_RATE;
+ p_service_cfg->ds_qos.max.burst = max_burst;
+ /* TBD priority */
+ p_service_cfg->ds_qos.max.traffic_priority = 2;
+ ret = bal_sw_dpp_llid_qos_config(unit, p_service_cfg);
+ /* Check for errors */
+ if (ret != BCM_ERR_OK)
+ {
+ /* Failure */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "Downstream QoS configuration failed for pon %u tid %u\n",
+ p_flow->data.access_int_id, tunnel_id);
+ break;
+ }
+ BCM_GPORT_UNICAST_QUEUE_GROUP_SET(pon, p_service_cfg->ds_qos.voq_flow_id);
+ sys_pon = p_service_cfg->ds_qos.voq_gport;
+ BCM_LOG(INFO, log_id_sw_util, " use voq_id 0x%x queue group 0x%x, voq_gport 0x%x to create PON LIFT\n", p_service_cfg->ds_qos.voq_flow_id, pon, sys_pon);
+
+ /* clear the VOQ stats here */
+ bal_sw_dpp_qos_clear_voq_stats(unit, sys_pon);
+ }
+ else
+ {
+ sys_pon = pon;
+ BCM_LOG(INFO, log_id_sw_util, " use pp port 0x%x to create PON LIFT\n", pon);
+ }
+
+ /* Configure the switch pon LIF based on classifier in the flow.
+ The pon LIF filter the ingress packets from PON, so use the classifier in the US direction.
+ This means, if the original flow configuration is for Downstream, use the reverse flow that locally created */
+
+ bcm_vlan_port_t_init(&vp);
+
+ /* preserve any incoming packet vlan tags, if vlan actions are required, do it using egress translation */
+ vp.flags = BCM_VLAN_PORT_OUTER_VLAN_PRESERVE | BCM_VLAN_PORT_INNER_VLAN_PRESERVE;
+ /* It is required to set the FEC flag so that the egress redirection action from the DS classification can
+ select the correct PON LIF to forward the packet */
+ vp.flags |= BCM_VLAN_PORT_FORWARD_GROUP;
+
+
+ switch(p_us_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ /* match both tunnel and outer tag on ingress PON */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_us_flow->data.classifier, classifier, o_pbits))
+ {
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL_PCP_VLAN;
+ vp.match_pcp = p_us_flow->data.classifier.o_pbits;
+ }
+ else
+ {
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL_VLAN;
+ }
+ break;
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ /* Otherwise match both tunnel and both outer and inner tags on ingress PON */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_us_flow->data.classifier, classifier, o_pbits))
+ {
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL_PCP_VLAN_STACKED;
+ vp.match_pcp = p_us_flow->data.classifier.o_pbits;
+ }
+ else
+ {
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL_VLAN_STACKED;
+ }
+ break;
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ /* Otherwise match tunnel tag on ingress PON */
+ {
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL;
+ }
+ break;
+ default:
+ /* should not reach here */
+ BCM_LOG(ERROR, log_id_sw_util, "Error, Unsupported packet type %d for pon LIF\n",p_us_flow->data.classifier.pkt_tag_type );
+ return BCM_ERR_INTERNAL;
+ }
+
+
+ vp.port = pon;
+ vp.match_tunnel_value = tunnel_id;
+ vp.egress_tunnel_value = tunnel_id;
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_us_flow->data.classifier, classifier, o_vid))
+ {
+ vp.match_vlan = p_us_flow->data.classifier.o_vid;
+ }
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_us_flow->data.classifier, classifier, i_vid))
+ {
+ vp.match_inner_vlan = p_us_flow->data.classifier.i_vid;
+ }
+ vp.vsi = 0; /* will be populated when the gport is added to service, using vswitch_port_add */
+
+ /* Create the vlan port (i.e., PON LIF) */
+ rv = bcm_vlan_port_create(unit, &vp);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_vlan_port_create pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ pon_gport = vp.vlan_port_id;
+ /* set pon gport to first element of the array */
+ flow_elm.pon_port[0] = pon_gport;
+
+ /* set PON port DISCARD mode to reflect the flow direction. When two BAL flows with same id and different directions
+ are configured, the DISCARD mode will be set back to NONE */
+ if (flow_elm.type == BAL_SW_FLOW_TYPE_DOWNSTREAM)
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Info, bcm_port_discard_set pon 0x%x to DISCARD_INGRESS\n", pon_gport);
+ rv = bcm_port_discard_set(unit, pon_gport, BCM_PORT_DISCARD_INGRESS);
+ }
+ else if (flow_elm.type == BAL_SW_FLOW_TYPE_UPSTREAM)
+ {
+ /* allow bi-direction for N:1 service */
+ if( BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_us_flow, flow, group_id) &&
+ BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_us_flow, flow, resolve_mac) &&
+ BCMOS_TRUE == p_us_flow->data.resolve_mac)
+ {
+ rv = BCM_E_NONE;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Info, bcm_port_discard_set pon 0x%x to DISCARD_EGRESS\n", pon_gport);
+ rv = bcm_port_discard_set(unit, pon_gport, BCM_PORT_DISCARD_EGRESS);
+ }
+ }
+ else
+ {
+ rv = BCM_E_NONE;
+ }
+
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_discard_set failed %d\n", rv);
+ /* ARAD does not support the DISCARD function as of 6.5.4 */
+#ifdef QAX_SWITCH
+ ret = BCM_ERR_INTERNAL;
+ break;
+#endif
+ }
+
+ // add pon gport to vswitch
+ rv = bcm_vswitch_port_add(unit, vsi, pon_gport);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_vswitch_port_add for pon 0x%x failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Info, bcm_vswitch_port_add for pon 0x%x, gport 0x%x\n", pon, pon_gport);
+ }
+
+ if(BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, group_id) &&
+ BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, resolve_mac) &&
+ BCMOS_TRUE == p_flow->data.resolve_mac)
+ {
+ /* for flows that need to resolve mac, don't forward unknown traffics */
+ BCM_LOG(DEBUG, log_id_sw_util, "pon %d:0x%x bypass downstream MC group join\n", pon, pon_gport);
+ }
+ else
+ {
+ // obtain encapsulation ID for legacy reason, used in ADD API */
+ rv = bcm_multicast_vlan_encap_get(unit, p_vsi_svc->ds_flood_grp_id, sys_pon, pon_gport, &pon_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_multicast_vlan_encap_get for pon failed %d\n", rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* join the downstream multicast group as a member of replication list */
+ rv = bcm_multicast_ingress_add(unit, p_vsi_svc->ds_flood_grp_id, sys_pon, pon_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_multicast_ingress_add for pon failed %d\n", rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* now set the type of packets that goes to the upstream flooding group (offset 0) */
+ rv = bcm_port_control_set(unit, pon_gport, bcmPortControlFloodUnknownUcastGroup, BAL_DPP_US_FLOOD_OFFSET);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_control_set ucast for pon failed %d\n", rv);
+ }
+ }
+ rv = bcm_port_control_set(unit, pon_gport, bcmPortControlFloodUnknownMcastGroup, BAL_DPP_US_FLOOD_OFFSET);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_control_set mcast for pon failed %d\n", rv);
+ break;
+ }
+ rv = bcm_port_control_set(unit, pon_gport, bcmPortControlFloodBroadcastGroup, BAL_DPP_US_FLOOD_OFFSET);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_control_set bcast for pon failed %d\n", rv);
+ break;
+ }
+ /* perform vlan translation on pon port, pon egress info is in the Downstream configuration */
+ if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_ds_flow, flow, action))
+ {
+ ret = bal_sw_util_dpp_invlanx(unit, p_us_flow, pon_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to perform ingress vlan translation on pon %d\n", pon);
+ break;
+ }
+ ret = bal_sw_util_dpp_evlanx(unit, p_ds_flow, pon_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to perform egress vlan translation on pon %d\n", pon);
+ break;
+ }
+ }
+ /* === PON LIF created === */
+
+ ii = 0; /* Start with the first NNI logical interface */
+ /* loop through all nni port, add them to vswitch, -1 indicate end of table */
+ /* Configure the switch nni LIF based on classifier in the flow.
+ The nni LIF filter the ingress packets from Network, so use the classifier in the DS direction.
+ This means, if the original flow configuration is for Upstream, use the reverse flow that locally created */
+ while(-1 != (nni = bal_bcm_net_inf_pbm_get(ii)))
+ {
+ /* skip nni port that is not in the same device or not valid */
+ if ( bal_bcm_net_inf_dev_get(ii) != unit ||
+ BCMOS_FALSE == bcm_topo_nni_is_valid(ii))
+ {
+ ii++;
+ continue;
+ }
+
+ /* if nni port is specified in the flow, skip the other nni ports */
+ if ( BCMBAL_CFG_PROP_IS_SET(p_ds_flow, flow, network_int_id) &&
+ ii != p_ds_flow->data.network_int_id
+ )
+ {
+ ii++;
+ continue;
+ }
+
+ /* create gport based on nni physical port number */
+
+ ret = bal_sw_util_dpp_vsi_service_port_add(unit, p_vsi_svc, svc_tag_indx, nni, &nni_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add nni %d to vsi\n", nni);
+ break;
+ }
+
+ flow_elm.net_port[flow_elm.num_net] = nni_gport;
+ flow_elm.num_net++;
+
+ /* perform vlan translation on nni port, nni egress info is in the Upstream configuration */
+ if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_us_flow, flow, action))
+ {
+ rv = bcm_vlan_control_port_set(unit, nni_gport, bcmVlanPortTranslateKeyFirst, bcmVlanTranslateKeyPortOuter);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to perform vlan control port set on nni %d\n", nni);
+ break;
+ }
+ ret = bal_sw_util_dpp_invlanx(unit, p_ds_flow, nni_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to perform ingress vlan translation on nni %d\n", nni);
+ break;
+ }
+
+ ret = bal_sw_util_dpp_evlanx(unit, p_us_flow, nni_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to perfrom egress vlan translation on nni %d\n", nni);
+ break;
+ }
+ }
+ /* if classifier is more than just port + VLAN tags, add ACL rule to re-direct packet to egress port.
+ This bypass the ingress LIF as LIF check VID only.
+ Upstream classification is expected to be done in ONU (onu add GEM based on classifiers for upstream) */
+ if( p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM &&
+ bal_sw_util_flow_ds_acl_cls_chk(p_ds_flow) == BCMOS_TRUE )
+ {
+ /* add re-direct rule */
+ if( BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_ds_flow, flow, network_int_id))
+ {
+ ret = bal_sw_util_dpp_acl_add(unit, p_ds_flow, &flow_elm, nni_gport, pon_gport);
+ }
+ else /* Rule need to match the network port, otherwise, it will apply to all ports - nni and pon */
+ {
+ BCMBAL_CFG_PROP_SET(p_ds_flow, flow, network_int_id, ii);
+ ret = bal_sw_util_dpp_acl_add(unit, p_ds_flow, &flow_elm, nni_gport, pon_gport);
+ BCMBAL_CFG_PROP_CLEAR(p_ds_flow, flow, network_int_id);
+ }
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add forwarding acl on nni %d, ret = %d\n", ret, ii);
+ break;
+ }
+ /* add a dft drop rule (priority 0) on the LIF to drop packets that match VID but no match for other fields */
+ ret = bal_sw_util_dpp_dft_acl_add(unit, p_ds_flow, &flow_elm, nni_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add default acl on nni=0x%x, ret = %d\n", nni_gport, ret);
+ break;
+ }
+ }
+ /* If the user needs to perfrom upstream classification (in addition to VID),
+ Add an ACL rule to re-direct packets. The ACL also allow upstream flows to be prioritized based on priority field */
+ if( p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM &&
+ bal_sw_util_flow_us_acl_cls_chk(p_us_flow) == BCMOS_TRUE &&
+ /* there are issues using traditional API for PON application when egress vlan translation and ingress ACL are both active.
+ Enable the ACL only when there is no vlan action - TBD */
+ BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action))
+ {
+ /* ACL requires an action, currently support trap or re-direct the flow.
+ TRAP has been handle in other path, here we require user to specify which port to re-direct.
+ Other options will be adding multiple ACL to cover all possible egress ports - TBD */
+ if( BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_us_flow, flow, network_int_id))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, Upstream classifier in addition to VID without NNI port set is not suppotred\n");
+ break;
+ }
+ else
+ {
+ ret = bal_sw_util_dpp_acl_add(unit, p_us_flow, &flow_elm, pon_gport, nni_gport);
+ }
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add forwarding acl on pon %d, ret = %d\n", ret, pon);
+ break;
+ }
+ /* add a default drop rule (priority 0) on the LIF to drop packets that match VID but no match for other fields */
+ ret = bal_sw_util_dpp_dft_acl_add(unit, p_us_flow, &flow_elm, pon_gport);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to add default acl on pon=0x%x, ret = %d\n", pon_gport, ret);
+ break;
+ }
+ }
+
+ ii++; /* Next NNI */
+ }
+ /* skip the rest if anything goes wrong */
+ if( ret != BCM_ERR_OK)
+ {
+ break;
+ }
+ /* Configure PCP/Cos to Traffic Class mapping. This has to be done after the NNI LIFs are created */
+ if (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM && BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, sla))
+ {
+ p_service_cfg->num_nni_gport = flow_elm.num_net;
+ for( ii = 0; ii < p_service_cfg->num_nni_gport; ii++)
+ {
+ p_service_cfg->nni_gport[ii] = flow_elm.net_port[ii];
+ }
+ ret = bal_sw_dpp_llid_set_qos_port_map(unit, p_service_cfg);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, fail to perfrom nni qos port map, ret = %d\n", ret);
+ break;
+ }
+ }
+
+ } while(0);
+
+ if( ret == BCM_ERR_OK)
+ {
+ /* add the flow info to the link list */
+ flow_elm.p_vsi_svc = p_vsi_svc;
+ flow_elm.vsi_svc_indx = svc_tag_indx;
+ flow_elm.num_pon = 1;
+ flow_elm.p_service_cfg = p_service_cfg;
+
+ /* nni ports are done in the nni loop */
+ flow_elm.valid = 1;
+ bal_sw_util_flow_list_insert(flow_elm);
+
+ BCM_LOG(INFO, log_id_sw_util, "Add flow_elm %d type %d, vswitch 0x%x, Success\n", flow_elm.id, flow_elm.type, p_vsi_svc->vswitch);
+ }
+ return ret;
+}
+
+
+/**
+ * @brief The internal flow remove function program DPP to release resource that
+ * were allocated during the ADD operation
+ *
+ * @param p_flow_elm a pointer to the internal flow list
+ *
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_flow_remove_int(bal_sw_flow *p_flow_elm)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ int rv, i, flow_id;
+ bal_sw_vsi_service *p_vsi_svc;
+ bal_sw_group_list *p_group_list;
+
+ if(p_flow_elm == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " invalid pointer to the internal flow list\n");
+ return BCM_ERR_INTERNAL;
+ }
+ p_vsi_svc = (bal_sw_vsi_service *) p_flow_elm->p_vsi_svc;
+ /* if anything go wrong, log a warning and continue release resources */
+ for(i = 0; i <p_flow_elm->num_pon; i++)
+ {
+ rv = bcm_vswitch_port_delete(p_flow_elm->device, p_vsi_svc->vswitch, p_flow_elm->pon_port[i]);
+ if(rv)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " vswitch pon port 0x%x delete failed %d\n", p_flow_elm->pon_port[i], rv);
+ }
+ rv = bcm_vlan_port_destroy(p_flow_elm->device, p_flow_elm->pon_port[i]);
+ if(rv)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " vswitch pon port 0x%x destroy failed %d\n", p_flow_elm->pon_port[i], rv);
+ }
+ p_flow_elm->pon_port[i] = 0;
+ }
+ p_flow_elm->num_pon = 0;
+
+ for(i = 0; i <p_flow_elm->num_net; i++)
+ {
+ ret = bal_sw_util_dpp_vsi_service_port_rem(p_flow_elm->device, p_flow_elm->p_vsi_svc, p_flow_elm->vsi_svc_indx, p_flow_elm->net_port[i]);
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " vsi service port 0x%x remove failed %d\n", p_flow_elm->net_port[i], ret);
+ }
+
+ p_flow_elm->net_port[i] = 0;
+ }
+ p_flow_elm->num_net = 0;
+
+ /* release vswitch */
+ if (p_vsi_svc)
+ {
+ /* remove the vsi if no more service, destroy function will do the counting */
+ ret = bal_sw_util_dpp_vsi_service_destroy(p_flow_elm->device, p_vsi_svc);
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " vsi service destroy failed %d\n", ret);
+ }
+ }
+ /* decrement the group reference counter in the group list */
+ if (p_flow_elm->group_id)
+ {
+ p_group_list = bal_sw_util_dpp_group_list_get_by_id(p_flow_elm->group_id);
+ if ( p_group_list == NULL)
+ {
+ BCM_LOG(WARNING, log_id_sw_util,
+ " WARNING: MC flow remove can't find the mc group %d in the list\n", p_flow_elm->group_id);
+ }
+ else
+ {
+ if(p_group_list->use_count)
+ {
+ p_group_list->use_count--;
+ }
+ else
+ {
+ BCM_LOG(WARNING, log_id_sw_util,
+ " WARNING: MC flow remove find the mc group %d in the list has no use_count\n", p_flow_elm->group_id);
+ }
+ }
+ }
+
+ /* relese trap */
+ if (p_flow_elm->trap_code)
+ {
+ rv = bcm_rx_trap_type_destroy(p_flow_elm->device, p_flow_elm->trap_code);
+ if(rv)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " rx trap %d destroy failed %d\n", p_flow_elm->trap_code, rv);
+ }
+ p_flow_elm->trap_code = 0;
+ p_flow_elm->trap_port = 0;
+ }
+
+ /* release acl, if any */
+ for(i = 0; i <p_flow_elm->num_eid; i++)
+ {
+ if (p_flow_elm->field_entry_id[i])
+ {
+ rv = bcm_field_entry_remove(p_flow_elm->device, p_flow_elm->field_entry_id[i]);
+ if(rv)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " field entry %d remove failed %d\n", p_flow_elm->field_entry_id[i], rv);
+ }
+ rv = bcm_field_entry_destroy(p_flow_elm->device, p_flow_elm->field_entry_id[i]);
+ if(rv)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " field entry %d destroy failed %d\n", p_flow_elm->field_entry_id[i], rv);
+ }
+ p_flow_elm->field_entry_id[i] = 0;
+ }
+ }
+ p_flow_elm->num_eid = 0;
+
+ /* release llid qos, if any */
+ if (p_flow_elm->p_service_cfg)
+ {
+ /* any error during cleanup will be reported, but continue anyway */
+ bal_sw_dpp_llid_qos_cleanup(p_flow_elm->device, (bal_sw_dpp_qos_service_cfg *)p_flow_elm->p_service_cfg);
+ bcmos_free(p_flow_elm->p_service_cfg);
+ p_flow_elm->p_service_cfg = NULL;
+ }
+
+ /* remove from the internal link list */
+ flow_id = p_flow_elm->id;
+ ret = bal_sw_util_flow_list_remove(p_flow_elm);
+ if(ret == BCM_ERR_OK)
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d is removed\n", flow_id);
+ ret = BCM_ERR_OK;
+ }
+ else
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " fail to remove flow %d w ret = %d\n", flow_id, ret);
+ ret = BCM_ERR_INTERNAL;
+ }
+ return ret;
+}
+
+/**
+ * @brief The flow remove function program DPP to release resource that
+ * were allocated during the ADD operation
+ *
+ * @param iwf_mode The InterWorking Function mode - DIRECT or PER-FLOW
+ * @param p_flow A pointer to the requested add flow info
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_flow_remove(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bal_sw_flow *p_flow_elm;
+ int ii, rv;
+ bcm_port_discard_t discard_type = BCM_PORT_DISCARD_NONE;
+
+ if(p_flow == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " invalid pointer to the bal flow\n");
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* make sure the flow id is in the link list, if not return success anyway (probably clearing a DOWN flow) */
+ p_flow_elm = bal_sw_util_flow_list_get_by_id (p_flow->key.flow_id);
+ if(p_flow_elm == NULL)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, " flow %d not exist the link list\n", p_flow->key.flow_id);
+ return BCM_ERR_OK;
+ }
+
+ /* if flow_elm has the requested direction, set switch to discard packets from the requested direction. */
+ if( (p_flow_elm->type & BAL_SW_FLOW_TYPE_DOWNSTREAM) &&
+ (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM)
+ )
+ {
+ discard_type = BCM_PORT_DISCARD_EGRESS;
+ }
+ else if ((p_flow_elm->type & BAL_SW_FLOW_TYPE_UPSTREAM) &&
+ (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ )
+ {
+ discard_type = BCM_PORT_DISCARD_INGRESS;
+ }
+ else if (p_flow_elm->type & BAL_SW_FLOW_TYPE_MULTICAST)
+ {
+ /* clear rhe type so that it can remove the flow below */
+ p_flow_elm->type &= ~BAL_SW_FLOW_TYPE_MULTICAST;
+ }
+
+ if (discard_type != BCM_PORT_DISCARD_NONE)
+ {
+ for(ii=0; ii<p_flow_elm->num_pon; ii++)
+ {
+ if(p_flow_elm->pon_port[ii] == 0)
+ {
+ /* if PON LIF is deleted, then continue to the next pon */
+ continue;
+ }
+ rv = bcm_port_discard_set(p_flow_elm->device, p_flow_elm->pon_port[ii], discard_type);
+ if (rv != BCM_E_NONE)
+ {
+ /* mark an error, but continue */
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_discard_set failed %d on pon 0x%x\n", rv, p_flow_elm->pon_port[ii]);
+ ret = BCM_ERR_INTERNAL;
+ }
+ }
+ if (BCM_ERR_OK == ret)
+ {
+ if( p_flow->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM)
+ {
+ p_flow_elm->type &= ~BAL_SW_FLOW_TYPE_DOWNSTREAM;
+ }
+ else if (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
+ {
+ p_flow_elm->type &= ~BAL_SW_FLOW_TYPE_UPSTREAM;
+ }
+ BCM_LOG(INFO, log_id_sw_util, " Success remove flow %d with type %d\n", p_flow->key.flow_id, p_flow->key.flow_type);
+ }
+ }
+ /* remove the flow from the list if everything is cleanup */
+ if(BAL_SW_FLOW_TYPE_NONE == p_flow_elm->type)
+ {
+ ret = bal_sw_util_dpp_flow_remove_int(p_flow_elm);
+ }
+
+ return ret;
+}
+
+
+
+/*******************************
+ * Helper routines below
+ *******************************/
+/**
+ * @brief Helper routine to reverse a flow i.e. an upstream flow is made a downstream flow
+ * and vice versa
+ *
+ * @param p_flow A pointer to the original flow
+ * @param p_flow_rev A pointer to the reversed flow
+ * @return error code
+ *
+ * @note for now it assumes an untagged or single tagged vlan flow with single vlan tag classificiation
+ */
+static bcmos_errno bal_sw_util_reverse_flow_create(bcmbal_flow_cfg *p_flow, bcmbal_flow_cfg *p_flow_rev)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ if ((p_flow == NULL) || (p_flow_rev == NULL))
+ {
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* reverse parameters in flow */
+ memcpy(p_flow_rev, p_flow, sizeof(bcmbal_flow_cfg));
+
+ p_flow_rev->key.flow_type = (p_flow->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ?
+ BCMBAL_FLOW_TYPE_DOWNSTREAM : BCMBAL_FLOW_TYPE_UPSTREAM);
+
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_mac))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, src_mac, p_flow->data.classifier.dst_mac);
+ }
+ else /* clear the src_mac presence mask in the reverse flow */
+ {
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, src_mac);
+ }
+
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_mac))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, dst_mac, p_flow->data.classifier.src_mac);
+ }
+ else /* clear the dst_mac presence mask in the reverse flow */
+ {
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, dst_mac);
+ }
+
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_port))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, src_port, p_flow->data.classifier.dst_port);
+ }
+ else /* clear the src_port presence mask in the reverse flow */
+ {
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, src_port);
+ }
+
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_port))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, dst_port, p_flow->data.classifier.src_port);
+ }
+ else /* clear the dst_port presence mask in the reverse flow */
+ {
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, dst_port);
+ }
+
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, dst_ip))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, src_ip, p_flow->data.classifier.dst_ip);
+ }
+ else /* clear the src_ip presence mask in the reverse flow */
+ {
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, src_ip);
+ }
+
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, src_ip))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, dst_ip, p_flow->data.classifier.src_ip);
+ }
+ else /* clear the dst_ip presence mask in the reverse flow */
+ {
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, dst_ip);
+ }
+
+
+ if (BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG))
+ {
+ BCMBAL_ACTION_CMD_ID_CLEAR(&(p_flow_rev->data.action), BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG);
+ BCMBAL_ACTION_CMD_ID_SET(&(p_flow_rev->data.action), BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG);
+
+ /* remove o_vid from action */
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.action, action, o_vid);
+
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ /* ADD on untagged packet result to single tagged on revert direction */
+ p_flow_rev->data.classifier.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_SINGLE_TAG;
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, o_vid, p_flow->data.action.o_vid);
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ /* ADD on single tagged packet result to double tagged on revert direction */
+ p_flow_rev->data.classifier.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG;
+ p_flow_rev->data.classifier.o_vid = p_flow->data.action.o_vid;
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, i_vid, p_flow->data.classifier.o_vid);
+ break;
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ default:
+ /* should not reach here */
+ break;
+ }
+ }
+ else if (BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG))
+ {
+ BCMBAL_ACTION_CMD_ID_CLEAR(&(p_flow_rev->data.action), BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG);
+ BCMBAL_ACTION_CMD_ID_SET(&(p_flow_rev->data.action), BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG);
+
+ /* add o_vid to action */
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.action, action, o_vid, p_flow->data.classifier.o_vid);
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ /* REMOVE on double tagged packet result to single tagged on revert direction */
+ p_flow_rev->data.classifier.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_SINGLE_TAG;
+ p_flow_rev->data.classifier.o_vid = p_flow->data.classifier.i_vid;
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, i_vid);
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ /* REMOVE on single tagged packet result to untagged on revert direction */
+ p_flow_rev->data.classifier.pkt_tag_type = BCMBAL_PKT_TAG_TYPE_UNTAGGED;
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, o_vid);
+ break;
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ default:
+ /* should not reach here */
+ break;
+ }
+ /* if the remove classifier has tpid attribute, set it when ADD in reverse direction */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_tpid))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.action, action, o_tpid, p_flow->data.classifier.o_tpid);
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.classifier, classifier, o_tpid);
+ }
+ }
+ else if (BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG))
+ {
+ /* swap output vid and classifier parameters */
+ p_flow_rev->data.action.o_vid = p_flow->data.classifier.o_vid;
+ p_flow_rev->data.classifier.o_vid = p_flow->data.action.o_vid;
+ }
+
+ if (BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_REMARK_PBITS))
+ {
+ /* swap output pbits and classifier parameters */
+ if(BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_pbits))
+ {
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.action, action, o_pbits, p_flow->data.classifier.o_pbits);
+ }
+ else
+ {
+ /* if the pbits remark is for packets with any o_pibts, then there is no clear REVERSE operation.
+ Set the reverse to NO pbits action. i.e pbits is a passthrough
+ */
+ BCMBAL_ATTRIBUTE_PROP_CLEAR(&p_flow_rev->data.action, action, o_pbits);
+ BCMBAL_ACTION_CMD_ID_CLEAR(&(p_flow_rev->data.action), BCMBAL_ACTION_CMD_ID_REMARK_PBITS);
+ }
+
+ BCMBAL_ATTRIBUTE_PROP_SET(&p_flow_rev->data.classifier, classifier, o_pbits, p_flow->data.action.o_pbits);
+ }
+ //else tbd
+
+
+ return ret;
+}
+
+/**
+ * @brief Helper routine to compare two flows for symmetry
+ *
+ * @param p_flow A pointer to the original flow
+ * @param p_ref_flow A pointer to the reference flow
+ * @return TRUE or FALSE
+ */
+bcmos_bool bal_sw_util_is_symmetry_flows(bcmbal_flow_cfg *p_flow, bcmbal_flow_cfg *p_ref_flow)
+{
+ bcmos_bool ret = BCMOS_TRUE;
+
+ /* compare the access interface */
+ if( BCMBAL_CFG_PROP_IS_SET(p_flow, flow, access_int_id) !=
+ BCMBAL_CFG_PROP_IS_SET(p_ref_flow, flow, access_int_id) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " access interface SET not the same for flow %d\n", p_flow->key.flow_id);
+ ret = BCMOS_FALSE;
+ }
+ else
+ {
+ if( (BCMBAL_CFG_PROP_IS_SET(p_flow, flow, access_int_id) || BCMBAL_CFG_PROP_IS_SET(p_ref_flow, flow, access_int_id)) &&
+ (p_flow->data.access_int_id != p_ref_flow->data.access_int_id) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d downstream/upstream access interface %d != %d \n",
+ p_flow->key.flow_id, p_flow->data.access_int_id, p_ref_flow->data.access_int_id );
+ ret = BCMOS_FALSE;
+ }
+ }
+ /* compare the network interface */
+ if( BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id) !=
+ BCMBAL_CFG_PROP_IS_SET(p_ref_flow, flow, network_int_id) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " network interface SET not the same for flow %d\n", p_flow->key.flow_id);
+ ret = BCMOS_FALSE;
+ }
+ else
+ {
+ if( (BCMBAL_CFG_PROP_IS_SET(p_flow, flow, network_int_id) ||BCMBAL_CFG_PROP_IS_SET(p_ref_flow, flow, network_int_id)) &&
+ (p_flow->data.network_int_id != p_ref_flow->data.network_int_id) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d downstream/upstream access interface %d != %d \n",
+ p_flow->key.flow_id, p_flow->data.network_int_id, p_ref_flow->data.network_int_id );
+ ret = BCMOS_FALSE;
+ }
+ }
+
+ /* if there is no action for the flow, packet type and VIDs should be the same */
+ /* compare the IPv4 addresses */
+ if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action) &&
+ BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(p_ref_flow, flow, action))
+ {
+ /* check packet type */
+ if( BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type) !=
+ BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_ref_flow->data.classifier, classifier, pkt_tag_type) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " packet type SET not the same for flow %d\n", p_flow->key.flow_id);
+ ret = BCMOS_FALSE;
+ }
+ else
+ {
+ if( BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, pkt_tag_type) &&
+ (p_flow->data.classifier.pkt_tag_type != p_ref_flow->data.classifier.pkt_tag_type) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d downstream/upstream packet type %d != %d \n",
+ p_flow->key.flow_id, p_flow->data.classifier.pkt_tag_type, p_ref_flow->data.classifier.pkt_tag_type );
+ ret = BCMOS_FALSE;
+ }
+ }
+
+ /* check the outer VID */
+ if( BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid) !=
+ BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_ref_flow->data.classifier, classifier, o_vid) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " outer vid SET not the same for flow %d\n", p_flow->key.flow_id);
+ ret = BCMOS_FALSE;
+ }
+ else
+ {
+ if( BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, o_vid) &&
+ (p_flow->data.classifier.o_vid != p_ref_flow->data.classifier.o_vid) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d downstream/upstream outer vid %d != %d \n",
+ p_flow->key.flow_id, p_flow->data.classifier.o_vid, p_ref_flow->data.classifier.o_vid );
+ ret = BCMOS_FALSE;
+ }
+ }
+ /* check the inner VID */
+ if( BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid) !=
+ BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_ref_flow->data.classifier, classifier, i_vid) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " inner vid SET not the same for flow %d\n", p_flow->key.flow_id);
+ ret = BCMOS_FALSE;
+ }
+ else
+ {
+ if( BCMBAL_ATTRIBUTE_PROP_IS_SET(&p_flow->data.classifier, classifier, i_vid) &&
+ (p_flow->data.classifier.i_vid != p_ref_flow->data.classifier.i_vid) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d downstream/upstream inner vid %d != %d \n",
+ p_flow->key.flow_id, p_flow->data.classifier.i_vid, p_ref_flow->data.classifier.i_vid );
+ ret = BCMOS_FALSE;
+ }
+ }
+
+ }
+ else /* if there is an action - action for VID must be symmetrical */
+ {
+ if(BCMOS_TRUE == BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG) &&
+ BCMOS_FALSE == BCMBAL_ACTION_CMD_ID_IS_SET(&(p_ref_flow->data.action), BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG) )
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d downstream/upstream outer vlan action not symmetrical \n", p_flow->key.flow_id );
+ ret = BCMOS_FALSE;
+ }
+ if(BCMOS_TRUE == BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG) &&
+ BCMOS_FALSE == BCMBAL_ACTION_CMD_ID_IS_SET(&(p_ref_flow->data.action), BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG))
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d upstream/downstream outer vlan action not symmetrical \n", p_flow->key.flow_id );
+ ret = BCMOS_FALSE;
+ }
+ if(BCMBAL_ACTION_CMD_ID_IS_SET(&(p_flow->data.action), BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG) !=
+ BCMBAL_ACTION_CMD_ID_IS_SET(&(p_ref_flow->data.action), BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG))
+ {
+ BCM_LOG(INFO, log_id_sw_util, " flow %d upstream/downstream outer vlan translation not symmetrical \n", p_flow->key.flow_id );
+ ret = BCMOS_FALSE;
+ }
+
+ }
+
+ return ret;
+}
+
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+
+/*@}*/
+
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_flow.h b/bal_release/src/core/util/switch/dpp/bal_dpp_flow.h
new file mode 100755
index 0000000..09bd8e5
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_flow.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_flow.h
+ *
+ * @brief Function Prototype for switch app flow functions for DPP
+ *
+ * @ingroup switch_app
+ */
+
+#ifndef _BAL_DPP_FLOW_H_
+#define _BAL_DPP_FLOW_H_
+
+#include "bal_switch_util.h"
+#include "bal_switch_flow.h"
+
+/*@{*/
+
+bcmos_errno bal_sw_util_dpp_flow_add(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow);
+bcmos_errno bal_sw_util_dpp_flow_remove(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow);
+bcmos_errno bal_sw_util_dpp_flow_remove_int(bal_sw_flow *p_flow_elm);
+void bal_sw_util_dpp_flow_init(void);
+/*@}*/
+
+#endif
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_group.c b/bal_release/src/core/util/switch/dpp/bal_dpp_group.c
new file mode 100644
index 0000000..05894fd
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_group.c
@@ -0,0 +1,706 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+ /**
+ * @file bal_dpp_group.c
+ * @brief BAL Switch util helper functions that handle group requests
+ * @addtogroup sw_util
+ */
+
+/*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include <bal_utils_msg.h>
+#include "bcmos_errno.h"
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <bcm/types.h>
+#include <sal/core/libc.h>
+#ifndef sal_memset
+#define sal_memset memset
+#endif
+#include <bcm/port.h>
+#include <bcm/vlan.h>
+#include <bcm/error.h>
+#include <bcm/multicast.h>
+
+#include "bal_dpp_group.h"
+#include "bal_switch_acc_term.h"
+#include "bal_dpp_vswitch.h"
+
+
+
+/* A local link list to keep track of group list */
+TAILQ_HEAD(bal_sw_group_list_head, bal_sw_group_list) g_swutil_group_list;
+
+/**
+ * @brief The group list init function prepare a link list to keep track of
+ * multicast group in the switch util
+ *
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_group_list_init(void)
+{
+ TAILQ_INIT(&g_swutil_group_list);
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The group list finish function release all resources allocated in the list
+ *
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_group_list_finish(void)
+{
+ bal_sw_group_list *current_entry, *p_temp_entry;
+
+ /* Free all the entries in the list */
+ TAILQ_FOREACH_SAFE(current_entry,
+ &g_swutil_group_list,
+ next_grp,
+ p_temp_entry)
+ {
+ /* Remove it from the list */
+ TAILQ_REMOVE(&g_swutil_group_list, current_entry, next_grp);
+
+ bcmos_free(current_entry);
+ }
+
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The group list search function by BAL group id
+ *
+ * @param grp_id the group id that need to match the entry in the list
+ * @return pointer to an element in the list, NULL if search failed
+ */
+bal_sw_group_list *bal_sw_util_dpp_group_list_get_by_id(uint32_t grp_id)
+{
+ bal_sw_group_list *p_entry, *p_temp;
+
+ TAILQ_FOREACH_SAFE(p_entry, &g_swutil_group_list, next_grp, p_temp)
+ {
+ if( p_entry->bal_grp_id == grp_id)
+ {
+ break;
+ }
+ }
+ /* if reach the end of the list, TAILQ_FOREACH_SAFE set the p_entry to NULL */
+ return p_entry;
+
+}
+
+/*
+ * @brief The group list insert function
+ *
+ * @param entry the group element to be added in the link list
+ * @return pointer to the newly inserted group in the list, NULL if operation failed
+*/
+static bal_sw_group_list *bal_sw_util_group_list_insert(bal_sw_group_list entry)
+{
+ bal_sw_group_list *p_new_entry;
+
+ p_new_entry = bcmos_calloc(sizeof(bal_sw_group_list));
+ if(NULL == p_new_entry)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "GROUP list insert out of memory\n");
+ return NULL;
+ }
+ *p_new_entry = entry;
+ TAILQ_INSERT_TAIL(&g_swutil_group_list, p_new_entry, next_grp);
+ return p_new_entry;
+}
+
+/*
+ * @brief The group list remove function
+ *
+ * @param p_entry Pointer to the group element in the link list result from the search functions
+ * @return error code
+*/
+static bcmos_errno bal_sw_util_group_list_remove(bal_sw_group_list *p_entry)
+{
+ TAILQ_REMOVE(&g_swutil_group_list, p_entry, next_grp);
+ bcmos_free(p_entry);
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The group list membership check function by port
+ * Validate if interface/svervice_port is already a member
+ *
+ * @param p_grp_port the interface that need to be matched in the list
+ * @param p_entry pointer to an entry in the group list
+ * @return index to the port member, -1 if not found
+ */
+static int bal_sw_util_dpp_group_list_membership_check(bal_sw_group_list *p_entry, bal_sw_group_port *p_grp_port)
+{
+ int i;
+
+ if(p_entry == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group membership check with NULL parameter\n");
+ return BCMOS_FALSE;
+ }
+
+ for(i=0; i<p_entry->num_port; i++)
+ {
+ if(p_entry->port[i].port == p_grp_port->port &&
+ p_entry->port[i].svc_port == p_grp_port->svc_port)
+ {
+ p_grp_port->gport = p_entry->port[i].gport;
+ return i;
+ }
+ }
+ return -1;
+}
+
+/**
+ * @brief The group list membership remove function by port
+ * remove interface/svervice_port from the group membership
+ *
+ * @param grp_port the interface that need to be matched in the list
+ * @param p_entry pointer to an entry in the group list
+ * @return boolen TRUE or FALSE
+ */
+static bcmos_bool bal_sw_util_dpp_group_list_membership_rem(bal_sw_group_list *p_entry, bal_sw_group_port grp_port)
+{
+ int i, rv;
+
+ if(p_entry == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group membership remove with NULL parameter\n");
+ return BCMOS_FALSE;
+ }
+
+ for(i=0; i<p_entry->num_port; i++)
+ {
+ if(p_entry->port[i].port == grp_port.port &&
+ p_entry->port[i].svc_port == grp_port.svc_port)
+ {
+ /* destroy the vlan port (i.e., PON LIF) */
+ if(p_entry->port[i].gport)
+ {
+ rv = bcm_vlan_port_destroy(p_entry->device, p_entry->port[i].gport);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "Warning, GROUP:bcm_vlan_port_destroy pon %d failed %d\n", p_entry->port[i].gport, rv);
+ /* Likely a bug in the 6.5.4 release, ignore for now
+ return BCMOS_FALSE;
+ */
+ }
+ p_entry->port[i].gport = 0;
+ }
+ break;
+ }
+ }
+
+ /* if can't find the port, just return OK */
+ if(i != p_entry->num_port)
+ {
+ /* pack the list */
+ bal_sw_group_port null_port={0};
+ for(; i<p_entry->num_port-1; i++)
+ {
+ p_entry->port[i] = p_entry->port[i+1];
+ }
+ p_entry->port[i] = null_port;
+ p_entry->num_port--;
+ }
+
+ return BCMOS_TRUE;
+}
+
+
+/**
+ * @brief The group create function create a multicast group that contains egress LIF.
+ * This group can later connects to virtual switch in multiple FLOWs.
+ *
+ * The pointer of the created group will be returned
+ *
+ * @param unit switch device id
+ * @param p_grp a pointer to the multicast group definition
+ *
+ * @return pointer to the group list entry, NULL if operation failed
+ */
+
+bal_sw_group_list *bal_sw_util_dpp_group_create(int unit, bcmbal_group_cfg *p_grp)
+{
+ bal_sw_group_list *p_grp_list, grp_list_elm;
+ int32_t multicast_id;
+ uint32_t svc_indx;
+ int rv, flags;
+ bal_sw_vsi_service *p_vsi_service;
+
+ if(p_grp == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group create with NULL parameter\n");
+ return NULL;
+ }
+ /* check group list */
+ p_grp_list = bal_sw_util_dpp_group_list_get_by_id(p_grp->key.group_id);
+ if(p_grp_list)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group create with group id %d already existed\n", p_grp->key.group_id);
+ return NULL;
+ }
+ /* alloc an entry in the group list*/
+ memset(&grp_list_elm, 0, sizeof(bal_sw_group_list));
+ grp_list_elm.device = unit;
+ grp_list_elm.bal_grp_id = p_grp->key.group_id;
+ p_grp_list = bal_sw_util_group_list_insert(grp_list_elm);
+ if(p_grp_list == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group create failed insert to group list\n");
+ return NULL;
+ }
+
+ /* create a vswitch with empty service, we need vsi to create the MC flooding group for egress */
+ p_vsi_service = bal_sw_util_dpp_vsi_service_create(unit, NULL, &svc_indx);
+ if(NULL == p_vsi_service)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "create vsi service for group failed \n");
+ bal_sw_util_group_list_remove(p_grp_list);
+ return NULL;
+ }
+
+ p_grp_list->p_vsi = p_vsi_service;
+
+ multicast_id = p_vsi_service->vswitch + BAL_DPP_MC_OFFSET;
+
+ rv = bcm_multicast_group_is_free(unit, multicast_id);
+ if (rv == BCM_E_EXISTS)
+ {
+ rv = bcm_multicast_destroy(unit, multicast_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "MC: bcm_multicast_destroy 0x%x failed %d \n", multicast_id, rv);
+ bal_sw_util_group_list_remove(p_grp_list);
+ return NULL;
+ }
+ }
+ flags = BCM_MULTICAST_INGRESS_GROUP | BCM_MULTICAST_WITH_ID | BCM_MULTICAST_TYPE_L2;
+ rv = bcm_multicast_create(unit, flags, &multicast_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "MC: in bcm_multicast_create 0x%x w ingress failed %d \n", multicast_id, rv);
+ bal_sw_util_group_list_remove(p_grp_list);
+
+ return NULL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "MC: vswitch flood group 0x%x created\n", multicast_id);
+ }
+
+ /* update the group list info */
+ p_grp_list->l2_grp_id = multicast_id;
+ return p_grp_list;
+}
+
+/**
+ * @brief The group add function add members to the multicast group.
+ * In this function, gourp members are PON interfaces
+ *
+ * @param unit switch device id
+ * @param p_grp a pointer to the multicast group definition
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_group_add(int unit, bcmbal_group_cfg *p_grp)
+{
+ bal_sw_group_list *p_grp_list;
+ int i, pon, rv, indx;
+ bcm_gport_t pon_gport;
+ bcmos_errno ret;
+ int pon_encap_id;
+ bcm_vlan_port_t vp;
+ uint32_t flood_grp;
+
+ if(p_grp == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group add with NULL parameter\n");
+ return BCM_ERR_PARM;
+ }
+ /* check if L2 group has been created */
+ p_grp_list = bal_sw_util_dpp_group_list_get_by_id(p_grp->key.group_id);
+ if(!p_grp_list)
+ {
+ BCM_LOG(INFO, log_id_sw_util, "group add will alloc a L2 MC group, group id %d \n", p_grp->key.group_id);
+ p_grp_list = bal_sw_util_dpp_group_create(unit, p_grp);
+ if(p_grp_list == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group add failed create L2 Mc group\n");
+ return BCM_ERR_NORES;
+ }
+ }
+
+
+ ret = BCM_ERR_OK;
+
+ for(i=0; i<p_grp->data.members.len; i++)
+ {
+ bcmbal_group_member_info *p_member = &p_grp->data.members.val[i];
+ bal_sw_group_port port_member;
+
+ /* find the L2 logical interface number */
+ pon = bal_bcm_pon_inf_pbm_get(p_member->intf_id);
+
+ /* check if interface is already a member in the group list */
+ port_member.port = pon;
+ port_member.svc_port = p_member->svc_port_id;
+ if( -1 != bal_sw_util_dpp_group_list_membership_check(p_grp_list, &port_member))
+ {
+ BCM_LOG(INFO, log_id_sw_util, "pon interface %d with service port %d already a member\n",p_member->intf_id, p_member->svc_port_id);
+ continue;
+ }
+
+ /* check if interface already has an entry in the group list */
+ port_member.port = pon;
+ port_member.svc_port = 0;
+ indx = bal_sw_util_dpp_group_list_membership_check(p_grp_list, &port_member);
+ if( -1 == indx)
+ {
+ /* make sure there is still room in the group list for new member */
+ if(p_grp_list->num_port >= MAX_PON_PORT)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Error, GROUP: Reach maximum number of membership in the group list\n");
+ ret = BCM_ERR_NORES;
+ break;
+ }
+ }
+ /* if group has a owner, create a LIF for each member */
+ if(p_grp->data.owner != BCMBAL_GROUP_OWNER_NONE)
+ {
+ /* Map the tunnel ID to a PON channel OTM port */
+ rv = bcm_port_pon_tunnel_map_set(unit,
+ pon,
+ p_member->svc_port_id,
+ pon);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Error, GROUP:bcm_port_pon_tunnel_map_set on pon %d failed %d"
+ " (have you chosen the correct intf_maptable?)\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Create the pon LIF to be DS only */
+ bcm_vlan_port_t_init(&vp);
+
+ /* preserve any incoming packet vlan tags, if vlan actions are required, do it using egress translation */
+ vp.flags = BCM_VLAN_PORT_OUTER_VLAN_PRESERVE | BCM_VLAN_PORT_INNER_VLAN_PRESERVE;
+ /* It is required to set the FEC flag so that the egress redirection action from the DS classification can
+ select the correct PON LIF to forward the packet */
+ vp.flags |= BCM_VLAN_PORT_FORWARD_GROUP;
+
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_TUNNEL;
+
+ vp.port = pon;
+ vp.match_tunnel_value = p_member->svc_port_id;
+ vp.egress_tunnel_value = p_member->svc_port_id;
+
+ vp.vsi = 0; /* will be populated when the gport is added to service, using vswitch_port_add */
+
+ /* Create the vlan port (i.e., PON LIF) */
+ rv = bcm_vlan_port_create(unit, &vp);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_vlan_port_create pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "Info, GROUP:bcm_vlan_port_create pon %d with tunnel %d success\n", pon, p_member->svc_port_id);
+ }
+
+ pon_gport = vp.vlan_port_id;
+ rv = bcm_port_discard_set(unit, pon_gport, BCM_PORT_DISCARD_INGRESS);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_port_discard_set on pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* select the flooding group */
+ if(p_grp->data.owner == BCMBAL_GROUP_OWNER_MULTICAST)
+ {
+ flood_grp = p_grp_list->l2_grp_id;
+ }
+ else
+ {
+ flood_grp = (p_grp_list->p_vsi)->ds_flood_grp_id;
+ }
+ /* join the L2 multicast group */
+ rv = bcm_multicast_vlan_encap_get(unit, flood_grp, pon, pon_gport, &pon_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_vlan_encap_get on pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ rv = bcm_multicast_ingress_add(unit, flood_grp, pon, pon_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_multicast_ingress_add on pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ BCM_LOG(INFO, log_id_sw_util, "Info, GROUP:pon %d join l2 mc group 0x%x success\n", pon, flood_grp);
+ /* update the group list membership */
+ port_member.gport = pon_gport;
+ }
+ else
+ {
+ port_member.gport = 0;
+ }
+ p_grp_list->port[p_grp_list->num_port] = port_member;
+ p_grp_list->num_port++;
+
+ }
+
+
+ return ret;
+}
+
+
+/**
+ * @brief The group remove function remove members from the multicast group.
+ * In this function, group members are PON interfaces
+ *
+ * @param unit switch device id
+ * @param p_grp a pointer to the multicast group definition
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_group_rem(int unit, bcmbal_group_cfg *p_grp)
+{
+ bal_sw_group_list *p_grp_list;
+ int i, pon, rv;
+ bcmos_errno ret;
+ int pon_encap_id;
+
+ if(p_grp == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group remove with NULL parameter\n");
+ return BCM_ERR_PARM;
+ }
+ /* check if L2 group has been created */
+ p_grp_list = bal_sw_util_dpp_group_list_get_by_id(p_grp->key.group_id);
+ if(!p_grp_list)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group remove can not find L2 Mc group %d\n", p_grp->key.group_id);
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* remove LIF for each member */
+ ret = BCM_ERR_OK;
+ for(i=0; i<p_grp->data.members.len; i++)
+ {
+ bcmbal_group_member_info *p_member = &p_grp->data.members.val[i];
+ bal_sw_group_port port_member;
+
+ /* find the L2 logical interface number */
+ pon = bal_bcm_pon_inf_pbm_get(p_member->intf_id);
+
+ /* check if interface is already removed from the group list */
+ port_member.port = pon;
+ port_member.svc_port = p_member->svc_port_id;
+ if( -1 == bal_sw_util_dpp_group_list_membership_check(p_grp_list, &port_member))
+ {
+ BCM_LOG(INFO, log_id_sw_util, "pon interface %d with service port %d is not a member\n",p_member->intf_id, p_member->svc_port_id);
+ continue;
+ }
+
+ /* if the member has a LIF assigned, remove it from the switch multicast group */
+ if(port_member.gport)
+ {
+ /* leave the L2 multicast group */
+ rv = bcm_multicast_vlan_encap_get(unit, p_grp_list->l2_grp_id, pon, port_member.gport, &pon_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_vlan_encap_get on pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ rv = bcm_multicast_ingress_delete(unit, p_grp_list->l2_grp_id, pon, pon_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_multicast_ingress_delete on pon %d failed %d\n", pon, rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ if( BCMOS_FALSE == bal_sw_util_dpp_group_list_membership_rem(p_grp_list, port_member))
+ {
+ BCM_LOG(INFO, log_id_sw_util, "pon interface %d with service port %d membership remove failed\n",p_member->intf_id, p_member->svc_port_id);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+/**
+ * @brief The group set function replace members from the multicast group.
+ * In this function, group members are PON interfaces
+ *
+ * @param unit switch device id
+ * @param p_grp a pointer to the multicast group definition
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_group_set(int unit, bcmbal_group_cfg *p_grp)
+{
+ bal_sw_group_list *p_grp_list;
+ bcmos_errno ret = BCM_ERR_OK;
+ int pon_encap_id;
+
+ if(p_grp == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group replace with NULL parameter\n");
+ return BCM_ERR_PARM;
+ }
+ /* check if L2 group has been created */
+ p_grp_list = bal_sw_util_dpp_group_list_get_by_id(p_grp->key.group_id);
+ if(!p_grp_list)
+ {
+ /* mark it OK to create group at the end */
+ ret = BCM_ERR_OK;
+ }
+ else if(p_grp_list->num_port)
+ {
+ /* remove all members from the group */
+ do
+ {
+ if( p_grp_list->port[0].gport)
+ {
+ /* leave the L2 multicast group */
+ if (BCM_E_NONE != bcm_multicast_vlan_encap_get(unit, p_grp_list->l2_grp_id, p_grp_list->port[0].port, p_grp_list->port[0].gport, &pon_encap_id))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_vlan_encap_get on pon %d failed\n", p_grp_list->port[0].port);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ if (BCM_E_NONE != bcm_multicast_ingress_delete(unit, p_grp_list->l2_grp_id, p_grp_list->port[0].port, pon_encap_id))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, GROUP:bcm_multicast_ingress_delete on pon %d failed\n", p_grp_list->port[0].port);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ if( BCMOS_FALSE == bal_sw_util_dpp_group_list_membership_rem(p_grp_list, p_grp_list->port[0]))
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group set fail to remove existing member interface %d\n",p_grp_list->port[0].port );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }while(p_grp_list->num_port);
+ }
+
+ if(ret == BCM_ERR_OK)
+ {
+ /* create/add the group */
+ return bal_sw_util_dpp_group_add(unit, p_grp);
+ }
+ return ret;
+}
+
+/**
+ * @brief The group destroy function free up a multicast group.
+ * The group will be removed from the group list.
+ * All L2 resources accociated with the group will be free.
+ *
+ * @param unit switch device id
+ * @param p_grp a pointer to the multicast group definition
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_group_destroy(int unit, bcmbal_group_cfg *p_grp)
+{
+ bal_sw_group_list *p_grp_list;
+ int rv;
+ bcmos_errno ret;
+
+ if(p_grp == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "group destroy with NULL parameter\n");
+ return BCM_ERR_PARM;
+ }
+ /* check group list */
+ p_grp_list = bal_sw_util_dpp_group_list_get_by_id(p_grp->key.group_id);
+ if(!p_grp_list)
+ {
+ BCM_LOG(INFO, log_id_sw_util, "group destroy with group id %d does not existed\n", p_grp->key.group_id);
+ return BCM_ERR_OK;
+ }
+ /* can't destroy if any flow is still reference it */
+ if(p_grp_list->use_count)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "group destroy with group id %d is busy\n", p_grp->key.group_id);
+ return BCM_ERR_INVALID_OP;
+ }
+
+ /* Do our best to clean up */
+ /* free resources used by all members */
+ ret = bal_sw_util_dpp_group_rem(unit, p_grp);
+ if (ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "MC: destroy group 0x%x failed to free members \n", p_grp_list->l2_grp_id);
+ }
+
+ /* free the L2 multicast group */
+ rv = bcm_multicast_destroy(unit, p_grp_list->l2_grp_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "MC: in bcm_multicast_destroy 0x%x failed %d \n", p_grp_list->l2_grp_id, rv);
+ }
+
+ /* clean up the vsi */
+ bal_sw_util_dpp_vsi_service_destroy(unit, p_grp_list->p_vsi);
+ /* remove from the list */
+ bal_sw_util_group_list_remove(p_grp_list);
+
+ return BCM_ERR_OK;
+}
+
+#endif /* LOOPBACK */
+/*@}*/
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_group.h b/bal_release/src/core/util/switch/dpp/bal_dpp_group.h
new file mode 100644
index 0000000..9d557fe
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_group.h
@@ -0,0 +1,80 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+ /**
+ * @file bal_dpp_group.h
+ * @brief BAL Switch util helper functions prototype
+ * @addtogroup sw_util
+ */
+#ifndef _BAL_DPP_GROUP_H_
+#define _BAL_DPP_GROUP_H_
+
+#include "bal_dpp_vswitch.h"
+#include "bal_switch_util.h"
+
+/*@{*/
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+typedef struct bal_sw_group_port bal_sw_group_port;
+struct bal_sw_group_port
+{
+ uint32_t port; /* group member physical port number */
+ uint32_t gport; /* group member gport id, i.e resource reference in the switch */
+ uint32_t svc_port; /* group member GEM id, in the PON world */
+};
+
+
+typedef struct bal_sw_group_list bal_sw_group_list;
+struct bal_sw_group_list
+{
+ uint32_t device; /* switch device id where the group applied */
+ uint32_t bal_grp_id; /* id reference in BAL */
+ uint32_t num_port; /* number of the member */
+ bal_sw_group_port port[MAX_PON_PORT]; /* member info structure */
+ uint32_t l2_grp_id; /* multicast id in L2 table */
+ uint32_t use_count; /* number of flows that reference this group */
+ bal_sw_vsi_service *p_vsi; /* vswitch service used by this GROUP */
+ TAILQ_ENTRY(bal_sw_group_list) next_grp;
+};
+
+
+extern bcmos_errno bal_sw_util_dpp_group_list_init(void);
+extern bcmos_errno bal_sw_util_dpp_group_list_finish(void);
+extern bal_sw_group_list *bal_sw_util_dpp_group_list_get_by_id(uint32_t grp_id);
+extern bal_sw_group_list *bal_sw_util_dpp_group_create(int unit, bcmbal_group_cfg *p_grp);
+extern bcmos_errno bal_sw_util_dpp_group_destroy(int unit, bcmbal_group_cfg *p_grp);
+extern bcmos_errno bal_sw_util_dpp_group_set(int unit, bcmbal_group_cfg *p_grp);
+extern bcmos_errno bal_sw_util_dpp_group_rem(int unit, bcmbal_group_cfg *p_grp);
+extern bcmos_errno bal_sw_util_dpp_group_add(int unit, bcmbal_group_cfg *p_grp);
+
+#endif /* TEST_SW_UTIL_LOOPBACK */
+/*@}*/
+#endif
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_interface.c b/bal_release/src/core/util/switch/dpp/bal_dpp_interface.c
new file mode 100644
index 0000000..f1433a3
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_interface.c
@@ -0,0 +1,127 @@
+/******************************************************************************
+ *
+ * <: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 TEST_SW_UTIL_LOOPBACK
+
+#include <bal_common.h>
+#include <bal_core.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_acc_term.h"
+#include "bal_switch_util.h"
+#include "bal_dpp_interface.h"
+
+#include <bcm/types.h>
+#include <bcm/port.h>
+
+/**
+ * @file bal_dpp_interface.c
+ * @brief BAL Switch util functions that handle interface requests on DUNE PACKET PROCESSOR
+ * @addtogroup sw_util
+ *
+ */
+
+/*@{*/
+
+
+/**
+ * @brief Set up pon interface with DPP
+ *
+ * This routine is called by sw_util_interface_set in the BAL core
+ * to execute DPP specific API for pon interface request
+ *
+ * @param p_interface_inst Pointer to interface instance
+ * @param opt_type UP/DOWN/RESTART the interface
+ * @return bcmos_errno
+ */
+bcmos_errno bal_sw_util_dpp_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if opt_type )
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ int rc = 0;
+ bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key;
+ int unit, port;
+
+ BCM_LOG(INFO, log_id_sw_util, " DPP - Got a interface SET: intf_type: %s, intf_id: %d, opt_type: %s\n",
+ (intf_key.intf_type == BCMBAL_INTF_TYPE_PON ? "PON":"NNI"),
+ intf_key.intf_id,
+ (opt_type == BAL_UTIL_OPER_IF_DOWN ? "DOWN":"UP"));
+
+ /* based on interface type get the device number and physical port number from associated table */
+ switch(intf_key.intf_type)
+ {
+ case BCMBAL_INTF_TYPE_PON:
+ unit = bal_bcm_pon_inf_dev_get(intf_key.intf_id);
+ port = bal_bcm_pon_inf_pbm_get(intf_key.intf_id);
+ break;
+ case BCMBAL_INTF_TYPE_NNI:
+ unit = bal_bcm_net_inf_dev_get(intf_key.intf_id);
+ port = bal_bcm_net_inf_pbm_get(intf_key.intf_id);
+ break;
+ default:
+ BCM_LOG(ERROR, log_id_sw_util, "Error, Unrecognized interface type %d\n", intf_key.intf_type);
+ return BCM_ERR_INTERNAL;
+ break;
+ }
+
+ switch (opt_type)
+ {
+ case BAL_UTIL_OPER_IF_DOWN:
+ rc = bcm_port_enable_set(unit, port, 0);
+ break;
+ case BAL_UTIL_OPER_IF_UP:
+ default:
+ /* disable */
+ rc = bcm_port_enable_set(unit, port, 0);
+ /* sleep 300 ms */
+ usleep(300000);
+ /* enable */
+ rc = bcm_port_enable_set(unit, port, 1);
+ /* Enable auto-negotiation if necessary */
+ if (intf_key.intf_type == BCMBAL_INTF_TYPE_NNI &&
+ bcmbal_is_nni_autoneg_on(intf_key.intf_id))
+ {
+ /* sleep 400 ms */
+ usleep(400000);
+ rc = rc ? rc : bcm_port_autoneg_set(unit, port, 1);
+ BCM_LOG(INFO, log_id_sw_util, "Enabled autoneg on NNI unit:port %d:%d. rc=%d\n", unit, port, rc);
+ }
+ break;
+ }
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_enable_set for pon failed %d\n", rc);
+ ret = BCM_ERR_INTERNAL;
+ }
+ return ret;
+}
+
+/*@}*/
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_interface.h b/bal_release/src/core/util/switch/dpp/bal_dpp_interface.h
new file mode 100644
index 0000000..36ae5f5
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_interface.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_interface.h
+ *
+ * @brief Function Prototype for switch app interface functions for DPP
+ *
+ * @ingroup switch_app
+ */
+
+#ifndef _BAL_DPP_INTERFACE_H_
+#define _BAL_DPP_INTERFACE_H_
+
+#include "bal_switch_util.h"
+
+/*@{*/
+
+extern bcmos_errno bal_sw_util_dpp_interface_set(acc_term_interface *p_interface_inst,
+ bal_util_oper_if opt_type);
+
+/*@}*/
+
+#endif
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_qos.c b/bal_release/src/core/util/switch/dpp/bal_dpp_qos.c
new file mode 100644
index 0000000..d667f2e
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_qos.c
@@ -0,0 +1,2390 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_qos.c
+ * @brief BAL Switch Util QoS configuration API
+ *
+ * This file contains the data structures and functions for
+ * configuring and managing Quality of Service (QoS) for services on
+ * DUNE Pack Processor (DPP).
+ *
+ * The scheduler setup is presented below. In addition to setting up
+ * the scheduling elements (SEs), the BAL_DPP_QOS configures an egress
+ * port shaper on each PON-side port, as well as a per-Access Link (GEMID/LLID)
+ * shaper to implement the downstream SLA for the subscriber service.
+ *
+ * Currently the BAL_DPP_QOS configures downstream QoS only (over the
+ * PON). Maple PON Link SLAs are used to implement upstream SLAs for
+ * the subscriber service in the BAL+Maple+DPP
+ * architecture. Additional upstream QoS for TM within DPP (over the
+ * NNIs) are considered an OEM System vendor responsibility. No
+ * implementation for upstream QoS is provided by the BAL_DPP_QOS.
+ *
+ *
+ * ********************************************************************************
+ *
+ */
+
+/*@{*/
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+#define BCM_PETRA_SUPPORT 1 /* TBD - this should be define in the Makefile of the ~/dpp directory */
+#define LINK_ARAD_LIBRARIES 1 /* SDK Make.config - BCM_88650_A0 */
+#define LINK_PPD_LIBRARIES 1 /* SDK Make.config - BCM_88650_A0 */
+#define INCLUDE_L3 1 /* bcm/l3.h support */
+
+#include <stdint.h> /* for compiler defined int64_t and uint64_t */
+
+#include "phymod_custom_config.h" /* resolve PHYMOD_xxx in phymod_system.h */
+#include "bcm/debug.h"
+#include "bcm/error.h"
+#include "bcm/l2.h"
+#include "bcm/mpls.h"
+#include "bcm/qos.h"
+#include "bcm/vlan.h"
+#include "bcm/vswitch.h"
+#include <soc/mcm/allenum.h>
+#include "bcm/field.h"
+#include <bcm/cosq.h>
+#include <bcm/stack.h>
+#include <bcm_int/dpp/alloc_mngr.h>
+#include <bcm_int/dpp/qos.h>
+#include <bcm_int/dpp/error.h>
+#include <bcm_int/dpp/utils.h>
+#include <bcm_int/dpp/qos.h>
+#include <soc/dpp/PPD/ppd_api_eg_vlan_edit.h>
+
+#include "bcm_dev_log.h"
+#include "bcmos_errno.h"
+#include "bal_switch_acc_term.h"
+#include "bal_switch_flow.h"
+#include "bal_switch_util.h"
+#include "bal_dpp_qos.h"
+
+/** @brief A global QoS configuration context */
+bal_sw_qos_cfg g_bal_bcm_qos_cfg = {0};
+
+/** @brief Pointer to global QoS configuration context */
+bal_sw_qos_cfg *gp_bal_bcm_qos_cfg = &g_bal_bcm_qos_cfg;
+
+/**
+ * @brief Number of traffic classes
+ */
+#define BAL_BCM_QOS_TC_NUM 8
+
+/**
+ * @brief PCP/CoS mapping to internal Traffic Class (TC)
+ *
+ * The mapping is as follows, where TC 0 maps to the lowest priority
+ * and TC 3 maps to the highest priority.
+ *
+ * PCP/DEI TC
+ * ------- --
+ * 0/0 0
+ * 0/1 0
+ * 1/0 0
+ * 1/1 0
+ * 2/0 1
+ * 2/1 1
+ * 3/0 1
+ * 3/1 1
+ * 4/0 2
+ * 4/1 2
+ * 5/0 2
+ * 5/1 2
+ * 6/0 3
+ * 6/1 3
+ * 7/0 3
+ * 7/1 3
+ *
+ * PCP values: 0 1 2 3 4 5 6 7
+ */
+const int g_bal_bcm_qos_tc_map[BAL_BCM_QOS_TC_NUM] = {0, 0, 1, 1, 2, 2, 3, 3};
+
+/**************************************************************************/
+/**
+ // * @brief Initialize the QOS Flow/VOQ ID resource pool
+ *
+ * This function initializes the QOS Flow/VOQ ID resource pool, which
+ * consists of an attribute representing the next ID value to allocate
+ * and a table containing free voq ID values.
+ *
+ * The BAL_DPP_QOS assumes four queues are assigned to each access port (GEMID/LLID) in
+ * the downstream direction. Four queues per access port is the smallest
+ * value of queues per access port supported by the DPP device.
+ *
+ * Note, in the BAL_DPP_QOS, the qos Flow and VOQ ID are set to the
+ * same value.
+ *
+ * @param p_pool Pointer to a voq ID pool
+ * @param init_value The initial value to use during voq ID allocation
+ * @param max_value The maximum value assigned by this pool
+ *
+ **************************************************************************/
+static void bal_sw_dpp_init_flow_id_pool(bal_sw_dpp_qos_flowid_pool *p_pool, uint32_t init_value, uint32_t max_value)
+{
+ /* Parameter checks */
+ BUG_ON(p_pool == NULL);
+
+ /* Initialize the data structure */
+ memset(p_pool, 0, sizeof(bal_sw_dpp_qos_flowid_pool));
+
+ /* Store the first value to be used as the voq ID */
+ p_pool->next_flow_id_value = init_value;
+
+ /* Store the maximum value assigned by the pool */
+ p_pool->max_value = max_value;
+
+ /* Initialize the free pool table */
+ TAILQ_INIT(&p_pool->free_table);
+}
+
+/**************************************************************************/
+/**
+ * @brief Clean up the qos Flow/VOQ ID resource pool
+ *
+ * This function cleans up the qos Flow/VOQ ID resource pool. It frees all
+ * of the memory used for bal_sw_dpp_qos_flowid_pool_entry_t's
+ *
+ * @param p_pool Pointer to a voq ID pool
+ *
+ **************************************************************************/
+static void bal_sw_dpp_cleanup_flow_id_pool(bal_sw_dpp_qos_flowid_pool *p_pool)
+{
+ bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
+
+ /* Parameter checks */
+ BUG_ON(p_pool == NULL);
+
+ while ((p_pool_entry = TAILQ_FIRST(&p_pool->free_table)) != NULL)
+ {
+ /* Remove the entry from the free pool table. */
+ TAILQ_REMOVE(&p_pool->free_table, p_pool_entry, entry);
+
+ /* Free the entry */
+ sal_free(p_pool_entry);
+ }
+}
+
+/**************************************************************************/
+/**
+ * @brief Allocate a qos Flow/VOQ ID from the pool
+ *
+ * This function allocates a Flow/VOQ ID from the resource pool. If
+ * there is a free voq ID entry in the free pool, the voq ID from
+ * the entry is used (i.e., returned to the caller) and the entry is
+ * freed. Otherwise, a new voq ID value is allocated and
+ * returned. This function returns an error if there are no voq IDs
+ * available.
+ *
+ * @param p_pool Pointer to a voq ID pool
+ * @param p_flow_id Pointer to the voq ID (value returned to caller)
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+static bcmos_errno bal_sw_dpp_qos_alloc_flow_id(bal_sw_dpp_qos_flowid_pool *p_pool, int *p_flow_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
+ uint32_t flow_id = 0;
+
+ /* Parameter checks */
+ BUG_ON(p_pool == NULL);
+ BUG_ON(p_flow_id == NULL);
+
+ /* Get an entry from the free pool */
+ p_pool_entry = TAILQ_FIRST(&p_pool->free_table);
+
+ /* If an entry exists from the free pool, use the voq ID from the
+ * entry.
+ */
+ if (p_pool_entry != NULL)
+ {
+ /* Remove the entry from the free pool. */
+ TAILQ_REMOVE(&p_pool->free_table, p_pool_entry, entry);
+
+ /* Use the voq ID from the entry */
+ flow_id = p_pool_entry->flow_id;
+
+ /* Free the entry */
+ sal_free(p_pool_entry);
+ }
+ else
+ {
+ /* Otherwise, use the next voq ID value (if available) */
+ if (p_pool->next_flow_id_value <= p_pool->max_value)
+ {
+ /* Use the next available voq ID value */
+ flow_id = p_pool->next_flow_id_value;
+
+ /* Increment the next_flow_id_value parameter */
+ p_pool->next_flow_id_value += BAL_BCM_QOS_QUEUES_PER_LLID;
+ }
+ }
+
+ /* Check to see if a voq ID value was available. */
+ if (flow_id == 0)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util, "%s(): No voq IDs available\n",
+ __FUNCTION__);
+ *p_flow_id = 0;
+ rc = BCM_ERR_NORES;
+ }
+ else
+ {
+ *p_flow_id = flow_id;
+ }
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Free a qos Flow/VOQ ID and return it to the resource pool
+ *
+ * This function "frees" a Flow/VOQ ID and returns it to the free
+ * pool. The free pool consists of a linked list of voq ID values
+ * that are available for reuse. When a voq ID is freed, memory is
+ * allocated to store the free voq ID value, which is appended to the
+ * link list used to implement the free pool.
+ *
+ * @param p_pool Pointer to a voq ID pool
+ * @param p_flow_id Pointer to the voq ID to free
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+static bcmos_errno bal_sw_dpp_qos_free_flow_id(bal_sw_dpp_qos_flowid_pool *p_pool, int *p_flow_id)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
+
+ /* Parameter checks */
+ BUG_ON(p_pool == NULL);
+ BUG_ON(p_flow_id == NULL);
+
+ /* Make sure there is something to free */
+ if (*p_flow_id == 0)
+ {
+ /* Nothing to free - just return */
+ return BCM_ERR_OK;
+ }
+
+ /* Allocate memory for a free pool entry */
+ p_pool_entry = sal_alloc(sizeof(bal_sw_dpp_qos_flowid_pool_entry), "voq ID Free Pool Entry");
+ if (p_pool_entry == NULL)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): No memory for bal_sw_dpp_qos_flowid_pool_entry_t for voq ID %u\n",
+ __FUNCTION__, *p_flow_id);
+
+ rc = BCM_ERR_NORES;
+ }
+ else
+ {
+ /* Initialize the entry */
+ memset(p_pool_entry, 0, sizeof(bal_sw_dpp_qos_flowid_pool_entry));
+
+ /* Store the voq ID */
+ p_pool_entry->flow_id = *p_flow_id;
+
+ /* Add the service entry to the table */
+ TAILQ_INSERT_TAIL(&p_pool->free_table, p_pool_entry, entry);
+
+ /* Clear the voq ID entry */
+ *p_flow_id = 0;
+ }
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Create the PCP and DEI to Traffic Class (TC) mapping
+ *
+ * This function creates the mapping from PCP/CoS and DEI bits in the
+ * frames received by DPP to the internal traffic class (TC) in
+ * DPP. The TC is used to determine the destination VOQ for the
+ * frame.
+ *
+ * Please see comments for @ref g_bal_bcm_qos_tc_map for a description of
+ * mapping.
+ *
+ * @param unit SDK unit number
+ * @param p_tc_map Pointer to PCP/DEI to TC map array
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+static bcmos_errno bal_sw_dpp_qos_tc_map_create(int unit, const int *p_tc_map)
+{
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bcm_qos_map_t l2_in_map;
+ int pcp = 0;
+ int dei = 0;
+ int32_t qos_map_id;
+
+ /* Parameter checks */
+ BUG_ON(p_tc_map == NULL);
+
+ /* Create the TC map object */
+ sdk_rc = bcm_qos_map_create(unit, BCM_QOS_MAP_INGRESS, &qos_map_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_qos_map_create failed with %s\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc));
+
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* Create a mapping for each PCP/CoS and DEI bit value. */
+ for (pcp = 0; pcp < BAL_BCM_QOS_TC_NUM; pcp++)
+ {
+ for (dei = 0; dei < 2; dei++)
+ {
+ bcm_qos_map_t_init(&l2_in_map);
+
+ /* Ingress PCP/CoS value */
+ l2_in_map.pkt_pri = pcp;
+
+ /* DEI Bit */
+ l2_in_map.pkt_cfi = dei;
+
+ /* Set internal priority for this ingress pri */
+ l2_in_map.int_pri = p_tc_map[pcp];
+
+ /* Set color for this ingress Priority */
+ l2_in_map.color = bcmColorGreen;
+
+ sdk_rc = bcm_qos_map_add(unit, BCM_QOS_MAP_L2, &l2_in_map, qos_map_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_qos_map_add failed with %s, for pcp %d, dei %d\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pcp, dei);
+
+ return BCM_ERR_INTERNAL;
+ }
+ }
+ }
+
+ gp_bal_bcm_qos_cfg->qos_port_map_id = qos_map_id;
+
+ return BCM_ERR_OK;
+}
+
+/**************************************************************************/
+/**
+ * @brief Clean up the PCP and DEI to Traffic Class (TC) map
+ *
+ * @param unit SDK unit number
+ *
+ **************************************************************************/
+static void bal_sw_dpp_qos_tc_map_cleanup(int unit)
+{
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bcm_qos_map_t l2_in_map;
+ int pcp = 0;
+ int dei = 0;
+
+ /* Delete all mapping entries */
+ for (pcp = 0; pcp < BAL_BCM_QOS_TC_NUM; pcp++)
+ {
+ for (dei = 0; dei < 2; dei++)
+ {
+ bcm_qos_map_t_init(&l2_in_map);
+
+ /* Ingress PCP/CoS value */
+ l2_in_map.pkt_pri = pcp;
+
+ /* DEI Bit */
+ l2_in_map.pkt_cfi = dei;
+
+ sdk_rc = bcm_qos_map_delete(unit, BCM_QOS_MAP_L2, &l2_in_map, gp_bal_bcm_qos_cfg->qos_port_map_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_qos_map_delete failed with %s, for pcp %d, dei %d\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pcp, dei);
+
+ /* Continue processing - don't halt because of errors during clearn up */
+ }
+ }
+ }
+
+ /* Delete the TC map object */
+ sdk_rc = bcm_qos_map_destroy(unit, gp_bal_bcm_qos_cfg->qos_port_map_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_qos_map_destroy failed with %s\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc));
+
+ /* Continue processing - don't halt because of errors during clearn up */
+ }
+}
+
+/**************************************************************************/
+/**
+ * @brief Initialize the BAL DPP QoS Module
+ *
+ * This function initializes the QoS module for the BAL BCM Switch Util.
+ * This function initializes the global QoS context, and
+ * sets up downstream scheduling hierarchy on each channelized
+ * PON-side port. Scheduling/QoS is applied to packets that egress the
+ * port.
+ *
+ * @param unit SDK unit number
+ * @param pon_mode pon interface mode
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_qos_init(int unit, bal_swapp_port_map_indx pon_mode)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bal_sw_dpp_qos_sched_pon_chan pon_chan;
+ uint32_t port_rate, pri_channel_rate, sec_channel_rate;
+ int ii, port_num;
+
+ /* Initialization */
+ memset(gp_bal_bcm_qos_cfg, 0, sizeof(*gp_bal_bcm_qos_cfg));
+
+ do /* Exception Block Start */
+ {
+ rc = bal_sw_dpp_qos_tc_map_create(unit, g_bal_bcm_qos_tc_map);
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "Failed to create the default QoS TC map\n");
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Get this module ID for this ARAD device. This is used by
+ * several of the bcm API calls during QoS setups.
+ */
+ sdk_rc = bcm_stk_modid_get(unit, &gp_bal_bcm_qos_cfg->mod_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_stk_modid_get failed with %s\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc));
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* set the port rate based on board type */
+ switch(pon_mode)
+ {
+ case BAL_SWAPP_PORT_MAP_GPON:
+ case BAL_SWAPP_PORT_MAP_GPON_V3:
+ port_rate = 2500000; /* 2.5G */
+ pri_channel_rate = 2500000; /* 2.5G */
+ sec_channel_rate = 0;
+ gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
+ break;
+ case BAL_SWAPP_PORT_MAP_EXP:
+ case BAL_SWAPP_PORT_MAP_EXP2:
+ case BAL_SWAPP_PORT_MAP_SVK4:
+ port_rate = 10000000; /* 10G */
+ pri_channel_rate = 10000000; /* 10G */
+ sec_channel_rate = 0;
+ gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
+ break;
+ case BAL_SWAPP_PORT_MAP_EPON_TDMA:
+ port_rate = BAL_BCM_QOS_DEFAULT_PORT_RATE; /* 12.5G */
+ pri_channel_rate = BAL_BCM_QOS_DEFAULT_10G_CHAN_RATE; /* 10.25G */
+ sec_channel_rate = BAL_BCM_QOS_DEFAULT_1G_CHAN_RATE; /* 2.25G */
+ gp_bal_bcm_qos_cfg->num_channels_per_pon = 2;
+ break;
+ case BAL_SWAPP_PORT_MAP_EPON_1G:
+ port_rate = 2500000; /* 2.5G */
+ pri_channel_rate = BAL_BCM_QOS_DEFAULT_1G_CHAN_RATE; /* 2.25G */
+ sec_channel_rate = 0;
+ gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
+ break;
+ case BAL_SWAPP_PORT_MAP_EPON_10G:
+ port_rate = BAL_BCM_QOS_DEFAULT_PORT_RATE; /* 12.5G */
+ pri_channel_rate = BAL_BCM_QOS_DEFAULT_10G_CHAN_RATE; /* 10.25G */
+ sec_channel_rate = 0;
+ gp_bal_bcm_qos_cfg->num_channels_per_pon = 1;
+ break;
+ default:
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): pon mode %d not supported\n",
+ __FUNCTION__, pon_mode);
+
+ return BCM_ERR_INTERNAL;
+ }
+ /*
+ * Initialize the egress scheduling for downstream QoS on each
+ * PON-side port.
+ */
+ ii = 0; /* Start with the first PON logical interface */
+ /* loop through all pon port, -1 indicate end of table */
+ while(-1 != (port_num = bal_bcm_pon_inf_pbm_get(ii)))
+ {
+ /*
+ * Default port settings
+ *
+ * Set the port shaper to rate based on physical layout on each board.
+ * On Epon, there are 2 channels on each port.
+ * The channel interface shapers are set to 10G and 2G for the 10G and 1G
+ * channels respectively. DPP will rely on flow control from
+ * Maple for back pressure.
+ */
+ bal_sw_dpp_qos_set_port_bandwidth(unit, port_num,
+ port_rate, BAL_BCM_QOS_DEFAULT_MAX_BURST);
+ bal_sw_dpp_qos_set_portchan_bandwidth(unit, port_num, BAL_BCM_SCHED_PON_CHAN_10G,
+ pri_channel_rate, BAL_BCM_QOS_DEFAULT_MAX_BURST);
+ if(gp_bal_bcm_qos_cfg->num_channels_per_pon > 1)
+ {
+ bal_sw_dpp_qos_set_portchan_bandwidth(unit, port_num, BAL_BCM_SCHED_PON_CHAN_1G,
+ sec_channel_rate, BAL_BCM_QOS_DEFAULT_MAX_BURST);
+ }
+ for (pon_chan = 0; pon_chan < gp_bal_bcm_qos_cfg->num_channels_per_pon; pon_chan++)
+ {
+ /* pass the logical port number - ii, to the port qos init function,
+ * the logical port number and the channel number will be mapped to
+ * packet process port number that used in qos configuration
+ */
+ rc = bal_sw_dpp_port_qos_init(unit, ii, pon_chan);
+
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "QoS setup failed for port %u pon_chan %u\n",
+ port_num, pon_chan);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ /* Exception Block - check for errors from the previous loop */
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ break;
+ }
+ ii++;
+ }
+
+ /* Check for errors */
+ if (rc != BCM_ERR_OK)
+ {
+ break;
+ }
+
+ /* Initialize the Flow/VOQ ID pools */
+ bal_sw_dpp_init_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_10g,
+ DEFAULT_QOS_VOQ_BASE_10G,
+ DEFAULT_QOS_VOQ_MAX_10G);
+
+ bal_sw_dpp_init_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_1g,
+ DEFAULT_QOS_VOQ_BASE_1G,
+ DEFAULT_QOS_VOQ_MAX_1G);
+
+ } while(0); /* Exception Block - End */
+
+ /* Check for errors */
+ if (rc != BCM_ERR_OK)
+ {
+ /* Failure */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "BAL BCM App not initialized, failed setting up the QoS module\n");
+
+ /* Cleanup */
+ bal_sw_dpp_qos_cleanup(unit);
+ }
+ else
+ {
+ /* Success */
+ BCM_LOG(INFO, log_id_sw_util,
+ "Successfully initialized the QoS module\n");
+ }
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Cleanup the BAL BCM APP QoS Module
+ *
+ * @param unit SDK unit number
+ *
+ **************************************************************************/
+void bal_sw_dpp_qos_cleanup(int unit)
+{
+ bcm_port_t port_num;
+ bal_sw_dpp_qos_sched_pon_chan pon_chan;
+ int ii;
+ /*
+ * Cleanup the egress scheduling for downstream QoS on each
+ * PON-side port.
+ */
+ ii = 0; /* Start with the first PON logical interface */
+ /* loop through all pon port, -1 indicate end of table */
+ while(-1 != (port_num = bal_bcm_pon_inf_pbm_get(ii)))
+ {
+ /* Clean up each channelized port */
+ for (pon_chan = 0; pon_chan < gp_bal_bcm_qos_cfg->num_channels_per_pon; pon_chan++)
+ {
+ bal_sw_dpp_port_qos_cleanup(unit, ii, pon_chan);
+ }
+ ii++;
+ }
+
+ /* Clean up the TC map */
+ bal_sw_dpp_qos_tc_map_cleanup(unit);
+
+ /* Free memory that was used for the Flow/VOQ ID pools */
+ bal_sw_dpp_cleanup_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_10g);
+ bal_sw_dpp_cleanup_flow_id_pool(&gp_bal_bcm_qos_cfg->flow_id_pool_1g);
+}
+
+/**************************************************************************/
+/**
+ * @brief Configure the rate shaper for a PON port
+ *
+ * This function configures the rate shaper (i.e., rate limit) for a
+ * PON side port. The rate limit and maximum burst size is set to the
+ * value specified in the function call. The maximum burst size is
+ * only set for max_burst values greater than '0'.
+ *
+ * @param unit SDK unit number
+ * @param pon_port PON port number
+ * @param bandwidth Shaper data rate in kbps
+ * @param max_burst Shaper maximum burst size in bytes
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_qos_set_port_bandwidth(int unit, bcm_port_t pon_port,
+ uint32_t bandwidth, uint32_t max_burst)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bcm_gport_t e2e_pon_gport;
+ bcm_gport_t e2e_parent_gport;
+
+ /* Parameter checks */
+ BUG_ON(pon_port > BAL_BCM_MAX_PON_NUM);
+
+ /* Get the gport object for the E2E interface for the specified
+ * pon_port
+ */
+ BCM_COSQ_GPORT_E2E_PORT_SET(e2e_pon_gport, pon_port);
+
+ do /* Exception Block Start */
+ {
+ /*
+ * Get the gport for the E2E Interface
+ */
+ sdk_rc = bcm_fabric_port_get(unit,
+ e2e_pon_gport,
+ 0,
+ &e2e_parent_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_fabric_port_get for Egress Port failed with %s for pon %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /*
+ * Set rate on the E2E Interface
+ */
+ sdk_rc = bcm_cosq_gport_bandwidth_set(unit,
+ e2e_parent_gport,
+ 0,
+ 0,
+ bandwidth,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_bandwidth_set for Egress Port failed with %s for pon %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Set the Burst */
+ if (max_burst > 0)
+ {
+ sdk_rc = bcm_cosq_control_set(unit,
+ e2e_parent_gport,
+ 0,
+ bcmCosqControlBandwidthBurstMax,
+ max_burst);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_control_set for MaxBurst failed with %s for pon %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ } while(0); /* Exception Block - End */
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Configure the rate shaper for a PON channel
+ *
+ * This function configures the rate shaper (i.e., rate limit) for a
+ * PON channel 10G. vs. 1G. The rate limit and maximum burst size is
+ * set to the value specified in the function call. The maximum burst
+ * size is only set for max_burst values greater than '0'.
+ *
+ * @param unit SDK unit number
+ * @param pon_port PON port number
+ * @param pon_chan PON channel (10G vs. 1G)
+ * @param bandwidth Shaper data rate in kbps
+ * @param max_burst Shaper maximum burst size in bytes
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_qos_set_portchan_bandwidth(int unit, bcm_port_t pon_port,
+ bal_sw_dpp_qos_sched_pon_chan pon_chan,
+ uint32_t bandwidth, uint32_t max_burst)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bcm_port_t pp_port;
+ bcm_gport_t e2e_gport;
+ bcm_gport_t local_gport;
+ bcm_gport_t e2e_tc_gport;
+ bcm_gport_t local_tc_gport;
+ uint32_t adj_bandwidth;
+
+ /* Parameter checks */
+ BUG_ON(pon_port > BAL_BCM_MAX_PON_NUM);
+ BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
+
+ /* Get the local port number for the specified device PON port number and channel */
+ pp_port = BAL_BCM_GET_PP_PORT(pon_port, pon_chan);
+
+ do /* Exception Block Start */
+ {
+ /* Apply a rate adjustment to the credit generator */
+ adj_bandwidth = bandwidth + ((uint32_t)(bandwidth * BAL_BCM_QOS_CREDIT_RATE_ADJ));
+
+ BCM_COSQ_GPORT_E2E_PORT_SET(e2e_gport, pp_port);
+ sdk_rc = bcm_cosq_gport_bandwidth_set(unit, e2e_gport, 0, 0, adj_bandwidth, 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_bandwidth_set for e2e_gport failed with %s for pon %u chan %u pp_port %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Apply a rate adjustment to the shaper */
+ adj_bandwidth = bandwidth + ((uint32_t)(bandwidth * BAL_BCM_QOS_SHAPER_RATE_ADJ));
+
+ BCM_GPORT_LOCAL_SET(local_gport, pp_port);
+ sdk_rc = bcm_cosq_gport_bandwidth_set(unit, local_gport, 0, 0, adj_bandwidth, 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_bandwidth_set for local_gport failed with %s for pon %u chan %u pp_port %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ BCM_COSQ_GPORT_E2E_PORT_TC_SET(e2e_tc_gport, pp_port);
+ sdk_rc = bcm_cosq_gport_bandwidth_set(unit, e2e_tc_gport, 0, 0, bandwidth, 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_bandwidth_set for e2e_tc_gport failed with %s for pon %u chan %u pp_port %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ BCM_COSQ_GPORT_PORT_TC_SET(local_tc_gport, pp_port);
+ sdk_rc = bcm_cosq_gport_bandwidth_set(unit, local_tc_gport, 0, 0, bandwidth, 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_bandwidth_set for local_tc_gport failed with %s for pon %u chan %u pp_port %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, pp_port);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ } while(0); /* Exception Block - End */
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Configure SP or WFQ scheduling for a PON channel
+ *
+ * This function configures scheduling for a PON channel (10G
+ * vs. 1G). If all of the specified weight values are non-zero, then
+ * WFQ is enabled on the PON channel. Otherwise, if one or more of the
+ * weight values is zero, strict priority (SP) scheduling will be used
+ * on this port.
+ *
+ * @param unit SDK unit number
+ * @param pon_port PON port number
+ * @param pon_chan PON channel (10G vs. 1G)
+ * @param p_wfq_cfg Pointer to the WFQ scheduler configuration
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_qos_set_ponchan_wfq_cfg(int unit, bcm_port_t pon_port,
+ bal_sw_dpp_qos_sched_pon_chan pon_chan, bal_sw_dpp_qos_wfq_cfg *p_wfq_cfg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
+ uint8_t wfq_lvl;
+ uint32_t weight;
+
+ /* Parameter checks */
+ BUG_ON(pon_port >= BAL_BCM_QOS_NUM_PON_PORTS);
+ BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
+
+ /* Get the scheduler configuration for the port. */
+ p_port_qos = &gp_bal_bcm_qos_cfg->pon[pon_port][pon_chan];
+
+ /* Assume WFQ is used until a zero weight value is encountered. */
+ p_port_qos->sched_type = BAL_BCM_SCHED_TYPE_WFQ;
+ for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ if (p_wfq_cfg->weights[wfq_lvl] == 0)
+ {
+ /* Use strict priority */
+ memset(&p_port_qos->pon_chan_weight_cfg, 0, sizeof(p_port_qos->pon_chan_weight_cfg));
+ p_port_qos->sched_type = BAL_BCM_SCHED_TYPE_SP;
+ break;
+ }
+ else
+ {
+ p_port_qos->pon_chan_weight_cfg[wfq_lvl] = p_wfq_cfg->weights[wfq_lvl];
+ }
+ }
+
+ /* If WFQ is being used, update the weight values in the PON
+ * channel's SE. Otherwise, the scheduling type is SP and there is
+ * nothing else to do.
+ */
+ if (p_port_qos->sched_type == BAL_BCM_SCHED_TYPE_WFQ)
+ {
+ /* Apply the weight configuration for each WFQ scheduling
+ * level to the hardware.
+ */
+ for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ /* The weight cannot exceed 4K on ARAD */
+ weight = p_port_qos->pon_chan_weight_cfg[wfq_lvl];
+ if (weight > BAL_BCM_SCHED_WFQ_MAX_WEIGHT)
+ {
+ BCM_LOG(WARNING, log_id_sw_util,
+ "Configured weight value %u is larger than the maximum supported by ARAD, capping value to %u, pon %u, chan %u, wfq_lvl %u\n",
+ weight, BAL_BCM_SCHED_WFQ_MAX_WEIGHT, pon_port, pon_chan, wfq_lvl);
+
+ /* If the weight value exceeds max, cap that value at 4K. */
+ weight = BAL_BCM_SCHED_WFQ_MAX_WEIGHT;
+ }
+
+ /* Configure the hardware */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_port_qos->wfq_scheduler[wfq_lvl],
+ 0,
+ BCM_COSQ_SP3,
+ weight);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for PON Channel WFQ SE failed with %s for pon %u, chan %u, wfq_lvl %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ }
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Initialize downstream QoS for a channelized PON port
+ *
+ * This function initializes downstream QoS for a channelized PON
+ * port, where scheduling/QoS is applied to packets that egress the
+ * port. Please refer to the "SCHEDULER MODEL" diagram at the top of
+ * this file.
+ *
+ * This function configures the Port-related scheduling elements
+ * (SEs), including the PON channel (10G vs. 1G) High Resolution
+ * Diff-serve (HR) SE. CIR flows are attached directly to the channel
+ * HR. Strict Priority (SP) and Weighted-Fair Queue (WFQ) SEs are
+ * created to implement DOCSIS Traffic Priority for EIR flows. After
+ * creating the SEs, each SE is connected to the hierarchy as shown in
+ * the diagram.
+ *
+ * @param unit SDK unit number
+ * @param log_pon logical PON port number
+ * @param pon_chan PON channel (10G vs. 1G)
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_port_qos_init(int unit, bcm_port_t log_pon, bal_sw_dpp_qos_sched_pon_chan pon_chan)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
+ bcm_gport_t mod_gport;
+ int flags = 0;
+ int wfq_lvl;
+ bcm_port_t pp_port, pon_port;
+
+ /* Parameter checks */
+ BUG_ON(log_pon >= BAL_BCM_QOS_NUM_PON_PORTS);
+ BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
+
+ BCM_LOG(DEBUG, log_id_sw_util,
+ "%s(): initializing QoS on port %d, %s channel w sche mode %s\n",
+ __FUNCTION__, log_pon, (pon_chan == BAL_BCM_SCHED_PON_CHAN_10G) ? "10G" : "1G",
+ (bal_bcm_ds_sched_mode_get()) ? "WFQ" : "SP");
+
+ /* Retrieve the QoS configuration for the specified channel, index by logical pon number */
+ p_port_qos = &gp_bal_bcm_qos_cfg->pon[log_pon][pon_chan];
+
+ /* Get Max rate scheduling mode from global setting */
+ /* TBD - the scheduling mode can be different for each port */
+ p_port_qos->sched_type = bal_bcm_ds_sched_mode_get();
+
+ /* get the pp port from the device port number */
+ pon_port = bal_bcm_pon_inf_pbm_get(log_pon);
+ pp_port = BAL_BCM_GET_PP_PORT(pon_port, pon_chan);
+
+ /*
+ * Setup downstream scheduling this channelized port
+ */
+
+ do /* Exception Block Start */
+ {
+ /*
+ * Get the mod port for this channel.
+ */
+ BCM_GPORT_MODPORT_SET(mod_gport, gp_bal_bcm_qos_cfg->mod_id, pp_port);
+ p_port_qos->mod_gport = mod_gport;
+
+ /* Initialize the channel weights to defaults values.
+ *
+ * By default strict priority is used, so these weight values
+ * are not "active". However, we need to set the weights to
+ * something non-zero during initialization.
+ *
+ * The default channel weights are...
+ * 32, 64, 128, 256, 512, 1024, 2048, 4096
+ */
+ p_port_qos->pon_chan_weight_cfg[0] = 32;
+ for (wfq_lvl=1; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ p_port_qos->pon_chan_weight_cfg[wfq_lvl] = 2 * p_port_qos->pon_chan_weight_cfg[wfq_lvl-1];
+ }
+
+ /*
+ * Channel HR (level 1)
+ *
+ * Get the OTM port HR for this PON channel. The rest of
+ * the downstream scheduling hierarchy is attached to this
+ * HR.
+ *
+ * The 'BCM_COSQ_GPORT_REPLACE' flag is passed into the
+ * bcm_cosq_gport_add() function call, which changes the
+ * scheduling type from the default mode to a SINGLE_WFQ
+ * mode.
+ */
+ BCM_COSQ_GPORT_E2E_PORT_SET(p_port_qos->pon_chan_scheduler, pp_port);
+ flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_HR_SINGLE_WFQ | BCM_COSQ_GPORT_REPLACE;
+ sdk_rc = bcm_cosq_gport_add(unit, pp_port, 1, flags, &p_port_qos->pon_chan_scheduler);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add (with REPLACE) for PON Channel HR failed with %s for pon %u chan %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ else
+ {
+
+ BCM_LOG(DEBUG, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add (with REPLACE) for PON Channel HR - gport 0x%x\n",
+ __FUNCTION__, p_port_qos->pon_chan_scheduler);
+ }
+ /*
+ * Strict Priority HR (level 2)
+ *
+ * Set up a Strict Priority HR scheduler for EIR (MAX Rate)
+ * flows. This SE is only used when the PON channel is running
+ * in Strict Priority mode.
+ */
+
+ /* Create the scheduler object */
+ flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_HR_ENHANCED;
+ sdk_rc = bcm_cosq_gport_add(unit, 0, 1, flags, &p_port_qos->sp_scheduler);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for MAX Rate SP HR failed with %s for pon %u chan %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ else
+ {
+
+ BCM_LOG(DEBUG, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for MAX Rate SP HR - gport 0x%x\n",
+ __FUNCTION__, p_port_qos->sp_scheduler);
+ }
+
+ /* Configure the priority for this scheduler. The SP SE is
+ * attached at priority '2'.
+ */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_port_qos->sp_scheduler,
+ 0,
+ BCM_COSQ_SP2,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for MAX Rate SP HR failed with %s for pon %u chan %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Attach the SP scheduler to the Channel HR. */
+ sdk_rc = bcm_cosq_gport_attach(unit,
+ p_port_qos->pon_chan_scheduler,
+ p_port_qos->sp_scheduler,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_attach for MAX Rate SP HR failed with %s for pon %u chan %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /*
+ * WFQ (level 2)
+ *
+ * Create FQ scheduling elements and attach one to each
+ * WFQ level. This is used to schedule EIR (MAX Rate)
+ * flows when the PON channel is running in WFQ mode.
+ */
+
+ /* Create a FQ scheduler for each WFQ level */
+ for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ /* Create the scheduler object */
+ flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_FQ;
+ sdk_rc = bcm_cosq_gport_add(unit, 0, 1, flags, &p_port_qos->wfq_scheduler[wfq_lvl]);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for MAX Rate WFQ failed with %s for pon %u chan %u wfq_lvl %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Configure the priority for this SE. (WFQ is SP3 on
+ * the Channel HR.)
+ */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_port_qos->wfq_scheduler[wfq_lvl],
+ 0,
+ BCM_COSQ_SP3,
+ p_port_qos->pon_chan_weight_cfg[wfq_lvl]);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for MAX Rate WFQ failed with %s for pon %u chan %u wfq_lvl %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Attach the FQ scheduler the WFQ on the Channel HR. */
+ sdk_rc = bcm_cosq_gport_attach(unit,
+ p_port_qos->pon_chan_scheduler,
+ p_port_qos->wfq_scheduler[wfq_lvl],
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_attach for MAX Rate WFQ failed with %s for pon %u chan %u wfq_lvl %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ } while(0); /* Exception Block - End */
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Clean up QoS for a PON-side port
+ *
+ * Each SE must be disconnected from the hierarchy before freeing the
+ * SE.
+ *
+ * @param unit SDK unit number
+ * @param pon_port PON port number
+ * @param pon_chan PON channel (10G vs. 1G)
+ *
+ **************************************************************************/
+void bal_sw_dpp_port_qos_cleanup(int unit, bcm_port_t pon_port, bal_sw_dpp_qos_sched_pon_chan pon_chan)
+{
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
+ int wfq_lvl;
+
+ /* Parameter checks */
+ BUG_ON(pon_port >= BAL_BCM_QOS_NUM_PON_PORTS);
+ BUG_ON(pon_chan >= BAL_BCM_SCHED_PON_CHAN_NUM);
+
+ /* Retrieve the QoS configuration for the specified port */
+ p_port_qos = &gp_bal_bcm_qos_cfg->pon[pon_port][pon_chan];
+
+ /*
+ * Clean up WFQ
+ */
+ for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ /* Disconnect the scheduler from the one above */
+ sdk_rc = bcm_cosq_gport_detach(unit,
+ p_port_qos->pon_chan_scheduler,
+ p_port_qos->wfq_scheduler[wfq_lvl],
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_detach for MAX Rate WFQ failed with %s for pon %u pon_chan %u wfq_lvl %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ sdk_rc = bcm_cosq_gport_delete(unit, p_port_qos->wfq_scheduler[wfq_lvl]);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_delete for MAX Rate WFQ failed with %s for pon %u pon_chan %u wfq_lvl %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan, wfq_lvl);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+ }
+
+ /*
+ * Clean up SP HR
+ */
+
+ /* Disconnect the scheduler from the one above */
+ sdk_rc = bcm_cosq_gport_detach(unit,
+ p_port_qos->pon_chan_scheduler,
+ p_port_qos->sp_scheduler,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_detach for MAX Rate SP HR failed with %s for pon %u pon_chan %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ sdk_rc = bcm_cosq_gport_delete(unit, p_port_qos->sp_scheduler);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_delete for MAX Rate SP HR failed with %s for pon %u pon_chan %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), pon_port, pon_chan);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+}
+
+/**************************************************************************/
+/**
+ * @brief Configure a rate shaper and maximum burst size for a PON Link
+ *
+ * This function configures the rate and maximum burst size for the
+ * specified shaper (MIN Rate vs. MAX Rate) for a PON Link (LLID).
+ *
+ * @param unit SDK unit number
+ * @param p_service_cfg Pointer to the service configuration entry
+ * @param sla_type Shaper type (MIN vs. MAX)
+ * @param bandwidth Data rate in Kbps (i.e., token bucket fill rate)
+ * @param max_burst Maximum burst size in bytes (i.e., token bucket size)
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_qos_set_llid_bandwidth(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg,
+ bal_sw_dpp_qos_sched_sla_type sla_type, uint32_t bandwidth, uint32_t max_burst)
+{
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bcm_gport_t scheduler_gport;
+
+ /* Parameter checks */
+ BUG_ON(p_service_cfg == NULL);
+
+ /* Get the scheduler gport that the VOQs are attached to (MIN vs. MAX) */
+ if (sla_type == BAL_BCM_SCHED_SLA_MIN_RATE)
+ {
+ scheduler_gport = p_service_cfg->ds_qos.min.scheduler_gport;
+ }
+ else
+ {
+ scheduler_gport = p_service_cfg->ds_qos.max.scheduler_gport;
+ }
+
+ /* Set the Rate - drain rate */
+ sdk_rc = bcm_cosq_gport_bandwidth_set(unit,
+ scheduler_gport,
+ 0,
+ 0,
+ bandwidth,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_bandwidth_set failed with %s for %s gport 0x%x\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), (sla_type == BAL_BCM_SCHED_SLA_MIN_RATE)? "SLA_MIN_RATE":"SLA_MAX_RATE", scheduler_gport);
+
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util,
+ "%s() set gport 0x%x with %s of %d\n",
+ __FUNCTION__, scheduler_gport,(sla_type == BAL_BCM_SCHED_SLA_MIN_RATE)? "SLA_MIN_RATE":"SLA_MAX_RATE", bandwidth);
+ }
+
+ /* Set the Burst - bucket size that hold the incoming frames */
+ sdk_rc = bcm_cosq_control_set(unit,
+ scheduler_gport,
+ 0,
+ bcmCosqControlBandwidthBurstMax,
+ max_burst);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_control_set for MaxBurst failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ return BCM_ERR_INTERNAL;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/**************************************************************************/
+/**
+ * @brief Configure downstream QoS for a PON Link (LLID)
+ *
+ * This function configures downstream QoS for a PON Link (LLID),
+ * which is represented by a tunnel ID in ARAD. Please refer to the
+ * "SCHEDULER MODEL" diagram at the top of this file. This function
+ * configures the PON Link SE and queues (VOQ + VOQ Connector) for the
+ * Link. The PON Link scheduler processes queues using strict
+ * priority. This function configures four queues for the Link, which
+ * is the smallest number of queues per LLID supported by
+ * ARAD. However, the BAL BCM App currently only makes use of a single
+ * queue.
+ *
+ * This function configures MIN (CIR) and MAX (EIR) rate shapers. If
+ * the MIN rate is disabled (i.e., bandwidth configured with a value
+ * of '0' kbps), the shaper is not "connected" to the port's MIN Rate
+ * SE.
+ *
+ * @param unit SDK unit number
+ * @param p_service_cfg Pointer to the service configuration entry
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_llid_qos_config(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
+ int flags = 0;
+ int cosq;
+ bcm_cosq_gport_connection_t connection;
+ bal_sw_dpp_qos_sched_pon_chan ds_pon_chan;
+ bcm_gport_t scheduler_gport;
+
+ /* Parameter checks */
+ BUG_ON(p_service_cfg == NULL);
+
+ /* Store the downstream PON rate, which will be used in several
+ * places throughout this function.
+ */
+ ds_pon_chan = p_service_cfg->ds_qos.pon_chan;
+
+ /* Retrieve the QoS configuration for the specified port */
+ p_port_qos = &gp_bal_bcm_qos_cfg->pon[p_service_cfg->pon_port][ds_pon_chan];
+
+ do /* Exception Block Start */
+ {
+ /* Allocate the voq ID from the free pool */
+ if (ds_pon_chan == BAL_BCM_SCHED_PON_CHAN_10G)
+ {
+ rc = bal_sw_dpp_qos_alloc_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_10g, &p_service_cfg->ds_qos.voq_flow_id);
+ }
+ else
+ {
+ rc = bal_sw_dpp_qos_alloc_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_1g, &p_service_cfg->ds_qos.voq_flow_id);
+ }
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): Unable to allocate voq ID for pon %u tid %u\n",
+ __FUNCTION__, p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* In the BAL BCM App, the VOQ ID is equal to the voq ID */
+ p_service_cfg->ds_qos.voq_id = p_service_cfg->ds_qos.voq_flow_id;
+
+ /*
+ * PON Link scheduler (level 2)
+ */
+ if (p_service_cfg->ds_qos.min.rate > 0)
+ {
+ /* Create a composite, strict priority scheduler for this PON
+ * Link. This is used to schedule between the queues assigned to
+ * this PON Link.
+ */
+ flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_CLASS_MODE1_4SP | BCM_COSQ_GPORT_COMPOSITE;
+ sdk_rc = bcm_cosq_gport_add(unit,
+ 0,
+ 1, /* Number of CoS levels */
+ flags,
+ &p_service_cfg->ds_qos.min.scheduler_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for PON Link SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* A single priority on the Channel HR handles all MIN Rates (CIRs). */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_service_cfg->ds_qos.min.scheduler_gport,
+ 0,
+ BCM_COSQ_SP1,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for Min Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Attach the PON Link scheduler to the Channel HR. */
+ sdk_rc = bcm_cosq_gport_attach(unit,
+ p_port_qos->pon_chan_scheduler,
+ p_service_cfg->ds_qos.min.scheduler_gport,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_attach for Min Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Save the gport of the parent SE (used for cleanup) */
+ p_service_cfg->ds_qos.min.parent_gport = p_port_qos->pon_chan_scheduler;
+
+ /* Configure the MIN Rate shaper */
+ rc = bal_sw_dpp_qos_set_llid_bandwidth(unit,
+ p_service_cfg,
+ BAL_BCM_SCHED_SLA_MIN_RATE,
+ p_service_cfg->ds_qos.min.rate,
+ p_service_cfg->ds_qos.min.burst);
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): Set MIN Rate shaper failed for pon %u tid %u\n",
+ __FUNCTION__, p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Set the gport for the MAX Rate scheduler */
+ BCM_COSQ_GPORT_COMPOSITE_SF2_SET(p_service_cfg->ds_qos.max.scheduler_gport, p_service_cfg->ds_qos.min.scheduler_gport);
+
+ /* Set the scheduler gport that the VOQs are attached to */
+ scheduler_gport = p_service_cfg->ds_qos.min.scheduler_gport;
+ }
+ else
+ {
+ /*
+ * MAX Rate only (level 2)
+ */
+ flags = BCM_COSQ_GPORT_SCHEDULER | BCM_COSQ_GPORT_SCHEDULER_CLASS_MODE1_4SP;
+ sdk_rc = bcm_cosq_gport_add(unit,
+ 0,
+ 1, /* Number of CoS levels */
+ flags,
+ &p_service_cfg->ds_qos.max.scheduler_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for PON Link SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Set the scheduler gport that the VOQs are attached to */
+ scheduler_gport = p_service_cfg->ds_qos.max.scheduler_gport;
+ }
+
+ /* The type of MAX Rate scheduling depends on what scheduling
+ * mode is configured on the PON channel (SP vs. WFQ).
+ */
+ if (p_port_qos->sched_type == BAL_BCM_SCHED_TYPE_SP)
+ {
+ /*
+ * Strict Priority (SP) scheduling is being used
+ */
+
+ /* Set the priority used for the attachment to the SP HR */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_service_cfg->ds_qos.max.scheduler_gport,
+ 0,
+ BCM_COSQ_SP0 + p_service_cfg->ds_qos.max.traffic_priority,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for Max Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Attach the PON Link scheduler to the SP HR. */
+ sdk_rc = bcm_cosq_gport_attach(unit,
+ p_port_qos->sp_scheduler,
+ p_service_cfg->ds_qos.max.scheduler_gport,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_attach for Max Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Save the gport of the parent SE (used for cleanup) */
+ p_service_cfg->ds_qos.max.parent_gport = p_port_qos->sp_scheduler;
+ }
+ else
+ {
+ /*
+ * Weighted Fair Queuing (WFQ) scheduling is being used
+ */
+
+ /* Set the priority used for the attachment to the FQ. */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_service_cfg->ds_qos.max.scheduler_gport,
+ 0,
+ BCM_COSQ_SP0,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for Max Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Attach the PON Link scheduler to the FQ. */
+ sdk_rc = bcm_cosq_gport_attach(unit,
+ p_port_qos->wfq_scheduler[p_service_cfg->ds_qos.max.traffic_priority],
+ p_service_cfg->ds_qos.max.scheduler_gport,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_attach for Max Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Save the gport of the parent SE (used for cleanup) */
+ p_service_cfg->ds_qos.max.parent_gport = p_port_qos->wfq_scheduler[p_service_cfg->ds_qos.max.traffic_priority];
+ }
+
+ /* Configure the MAX Rate shaper */
+ rc = bal_sw_dpp_qos_set_llid_bandwidth(unit,
+ p_service_cfg,
+ BAL_BCM_SCHED_SLA_MAX_RATE,
+ p_service_cfg->ds_qos.max.rate,
+ p_service_cfg->ds_qos.max.burst);
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): Set MAX Rate shaper failed for pon %u tid %u\n",
+ __FUNCTION__, p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ break;
+ }
+
+ /*
+ * Create a VOQ connector (level 3)
+ */
+
+ /* Create the VOQ connector object for a bundle of four queues */
+ flags = BCM_COSQ_GPORT_VOQ_CONNECTOR | BCM_COSQ_GPORT_WITH_ID;
+ BCM_COSQ_GPORT_VOQ_CONNECTOR_SET(p_service_cfg->ds_qos.voq_connector_gport, p_service_cfg->ds_qos.voq_flow_id);
+ sdk_rc = bcm_cosq_gport_add(unit,
+ p_port_qos->mod_gport,
+ BAL_BCM_QOS_QUEUES_PER_LLID,
+ flags,
+ &p_service_cfg->ds_qos.voq_connector_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for VOQ Connector failed with %s for pon %u tid %u voq ID %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc),
+ p_service_cfg->pon_port,
+ p_service_cfg->tunnel_id,
+ p_service_cfg->ds_qos.voq_flow_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Set the traffic class for each queue and attach the VOQ
+ * connector to the PON Link scheduler.
+ */
+ for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
+ {
+ /* Set the traffic class for the queue */
+ sdk_rc = bcm_cosq_gport_sched_set(unit,
+ p_service_cfg->ds_qos.voq_connector_gport,
+ cosq,
+ BCM_COSQ_SP3 - cosq,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_sched_set for VOQ Connector failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Attach the connection for each queue to the PON Link
+ * scheduler, based on the traffic class.
+ */
+ sdk_rc = bcm_cosq_gport_attach(unit,
+ scheduler_gport,
+ p_service_cfg->ds_qos.voq_connector_gport,
+ cosq);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_attach for VOQ Connector failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ /* Exception Block - check for errors from the previous loop */
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ break;
+ }
+
+ /*
+ * Create a VOQ (level 3)
+ */
+ flags = BCM_COSQ_GPORT_UCAST_QUEUE_GROUP | BCM_COSQ_GPORT_TM_FLOW_ID | BCM_COSQ_GPORT_WITH_ID;
+ BCM_GPORT_UNICAST_QUEUE_GROUP_SET(p_service_cfg->ds_qos.voq_gport, p_service_cfg->ds_qos.voq_id);
+ sdk_rc = bcm_cosq_gport_add(unit,
+ p_port_qos->mod_gport,
+ BAL_BCM_QOS_QUEUES_PER_LLID,
+ flags,
+ &p_service_cfg->ds_qos.voq_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_add for VOQ failed with %s for voq id %u, voq gport 0x%x, pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->ds_qos.voq_id, p_service_cfg->ds_qos.voq_gport,
+ p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* QAX not support per Queue compensation */
+#ifndef QAX_SWITCH
+ /* Start - header adjust */
+ {
+ /*
+ * If necessary, adjust the packet header overhead to match
+ * the configured value.
+ */
+ int32_t val = 0;
+ int32_t cfg_dpp_hdr_size = 0;
+
+ /* Calculate the expected DPP header size, which depends on
+ * whether or not traffic is untagged, PB tagged, ICT
+ * tagged, or Shared Vlan tagged. If the traffic is tagged
+ * (either PB, ICT, or Shared Vlan), there are five fewer
+ * bytes in the DPP header.
+ */
+ cfg_dpp_hdr_size = DEFAULT_QOS_DPP_PKT_HDR_SIZE;
+ if (p_service_cfg->service_type != BAL_BCM_SVC_TYPE_IP)
+ {
+ cfg_dpp_hdr_size -= BAL_BCM_DPP_FLOWID_HDR_SIZE;
+ }
+
+ /* If the traffic is ICT stack mode or Shared Vlan tagged, we
+ * need to exclude the Vlan tag overhead from the bandwidth
+ * calculation (i.e., add four bytes of overhead).
+ */
+ if (((p_service_cfg->service_type == BAL_BCM_SVC_TYPE_ICT) /*&& (p_service_cfg->ictStkType != BAL_BCM_ICT_STACK_TYPE_NONE)*/)||
+ (p_service_cfg->service_type == BAL_BCM_SVC_TYPE_SHVLAN))
+ {
+ cfg_dpp_hdr_size += BAL_BCM_QOS_SINGLE_VLAN_TAG_HDR_SIZE;
+ }
+
+ /* Get the header length */
+ sdk_rc = bcm_cosq_control_get(unit,
+ p_service_cfg->ds_qos.voq_gport,
+ 0,
+ bcmCosqControlPacketLengthAdjust,
+ &val);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_control_get for bcmCosqControlPacketLengthAdjust failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* If current length does not match the configured length,
+ * configure it now.
+ */
+ if (val != cfg_dpp_hdr_size)
+ {
+ /* Debug */
+ BCM_LOG(INFO, log_id_sw_util,
+ "%s(): modifying value of bcmCosqControlPacketLengthAdjust from %u to %u for pon %u tid %u\n",
+ __FUNCTION__,
+ val,
+ cfg_dpp_hdr_size,
+ p_service_cfg->pon_port,
+ p_service_cfg->tunnel_id);
+
+ /* Adjust the packet length calculated above. This has to
+ * be configured for each queue (cosq) in the voq
+ * group.
+ */
+ for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
+ {
+ /* Adjust the packet length calculated above. */
+ sdk_rc = bcm_cosq_control_set(unit,
+ p_service_cfg->ds_qos.voq_gport,
+ cosq,
+ bcmCosqControlPacketLengthAdjust,
+ cfg_dpp_hdr_size);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_control_set for bcmCosqControlPacketLengthAdjust for cosq %d failed with %s for pon %u tid %u\n",
+ __FUNCTION__, cosq, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+
+ /* Exception Block - check for errors from the previous loop */
+ if (rc != BCM_ERR_OK)
+ {
+ /* Error */
+ break;
+ }
+ }
+ } /* End - header adjustment */
+#endif
+ /*
+ * Connect a VOQ to a VOQ connector
+ */
+
+ /* Connect VOQ to the VOQ connector for the ingress direction */
+ connection.flags = BCM_COSQ_GPORT_CONNECTION_INGRESS;
+ connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
+ connection.voq = p_service_cfg->ds_qos.voq_gport;
+ connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
+
+ sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_connection_set for INGRESS failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* Connect VOQ to the VOQ connector for the egress direction */
+ connection.flags = BCM_COSQ_GPORT_CONNECTION_EGRESS;
+ connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
+ connection.voq = p_service_cfg->ds_qos.voq_gport;
+ connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
+
+ sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_cosq_gport_connection_set for EGRESS failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ rc = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ } while(0); /* Exception Block - End */
+
+ /* Check for errors */
+ if (rc != BCM_ERR_OK)
+ {
+ /* Failure */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "Downstream QoS setup failed for pon %u tid %u\n",
+ p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Cleanup */
+ bal_sw_dpp_llid_qos_cleanup(unit, p_service_cfg);
+ }
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Configure downstream QoS Port Map for a PON Link (LLID)
+ *
+ * This function configures downstream QoS Port Map for a PON Link
+ * (LLID), which is represented by a tunnel ID in ARAD. This sets the
+ * default traffic class (TC) value for VLAN tags being inserted or
+ * modified.
+ *
+ * @param unit SDK unit number
+ * @param p_service_cfg Pointer to the service configuration entry
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_llid_set_qos_port_map(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ int i;
+ /* Parameter checks */
+ BUG_ON(p_service_cfg == NULL);
+
+ /* Set the QoS Port Map for the NNI LIF */
+ for(i = 0; i < p_service_cfg->num_nni_gport; i++)
+ {
+ sdk_rc = bcm_qos_port_map_set(unit, p_service_cfg->nni_gport[i], gp_bal_bcm_qos_cfg->qos_port_map_id, -1);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): bcm_qos_port_map_set for nni_index %d returned with failure code '%s'\n",
+ __FUNCTION__, i, bcm_errmsg(sdk_rc));
+
+ rc = BCM_ERR_INTERNAL;
+ }
+ }
+
+ return rc;
+}
+
+/**************************************************************************/
+/**
+ * @brief Clean up QoS for a PON Link (LLID)
+ *
+ * Each SE and VOQ must be disconnected from the hierarchy before
+ * freeing the SE and VOQ objects.
+ *
+ * @param unit SDK unit number
+ * @param p_service_cfg Pointer to the service configuration entry
+ *
+ **************************************************************************/
+void bal_sw_dpp_llid_qos_cleanup(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg)
+{
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ int cosq;
+ bcm_cosq_gport_connection_t connection;
+ bal_sw_dpp_qos_sched_pon_chan ds_pon_chan;
+ bcm_gport_t scheduler_gport;
+
+ /* Parameter checks */
+ BUG_ON(p_service_cfg == NULL);
+
+ /* Store the downstream PON rate, which will be used in several
+ * places throughout this function.
+ */
+ ds_pon_chan = p_service_cfg->ds_qos.pon_chan;
+
+ /* Get the scheduler gport that the VOQs are attached to */
+ if (p_service_cfg->ds_qos.min.rate > 0)
+ {
+ scheduler_gport = p_service_cfg->ds_qos.min.scheduler_gport;
+ }
+ else
+ {
+ scheduler_gport = p_service_cfg->ds_qos.max.scheduler_gport;
+ }
+
+ /* Disconnect VOQ from the VOQ connector for the egress direction */
+ connection.flags = BCM_COSQ_GPORT_CONNECTION_EGRESS | BCM_COSQ_GPORT_CONNECTION_INVALID;
+ connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
+ connection.voq = p_service_cfg->ds_qos.voq_gport;
+ connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
+
+ sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_connection_set for DISCONNECT EGRESS failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ /* Disconnect VOQ from the VOQ connector for the ingress direction */
+ connection.flags = BCM_COSQ_GPORT_CONNECTION_INGRESS | BCM_COSQ_GPORT_CONNECTION_INVALID;
+ connection.remote_modid = gp_bal_bcm_qos_cfg->mod_id;
+ connection.voq = p_service_cfg->ds_qos.voq_gport;
+ connection.voq_connector = p_service_cfg->ds_qos.voq_connector_gport;
+
+ sdk_rc = bcm_cosq_gport_connection_set(unit, &connection);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_connection_set for DISCONNECT INGRESS failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ /* Delete the VOQ */
+ sdk_rc = bcm_cosq_gport_delete(unit, p_service_cfg->ds_qos.voq_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_delete for VOQ failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ /* Disconnect the VOQ connector */
+ for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
+ {
+ sdk_rc = bcm_cosq_gport_detach(unit,
+ scheduler_gport,
+ p_service_cfg->ds_qos.voq_connector_gport,
+ cosq);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_detach for VOQ Connector failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+ }
+
+ /* Delete the VOQ connector */
+ sdk_rc = bcm_cosq_gport_delete(unit, p_service_cfg->ds_qos.voq_connector_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_delete for VOQ Connector failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ /* If a MIN rate was configured for this PON Link, disconnect the
+ * PON Link scheduler from the MIN Rate scheduler.
+ */
+ if (p_service_cfg->ds_qos.min.rate > 0)
+ {
+ /* Detach from the parent SE */
+ sdk_rc = bcm_cosq_gport_detach(unit,
+ p_service_cfg->ds_qos.min.parent_gport,
+ p_service_cfg->ds_qos.min.scheduler_gport,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_detach for MIN Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+ }
+
+ /* Disconnect the PON Link scheduler from the MAX Rate scheduler. */
+ sdk_rc = bcm_cosq_gport_detach(unit,
+ p_service_cfg->ds_qos.max.parent_gport,
+ p_service_cfg->ds_qos.max.scheduler_gport,
+ 0);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_detach for MAX Rate SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ /* Delete the PON Link scheduler */
+ sdk_rc = bcm_cosq_gport_delete(unit, scheduler_gport);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(WARNING, log_id_sw_util,
+ "%s(): bcm_cosq_gport_delete for PON Link SE failed with %s for pon %u tid %u\n",
+ __FUNCTION__, bcm_errmsg(sdk_rc), p_service_cfg->pon_port, p_service_cfg->tunnel_id);
+
+ /* Continue cleanup, don't halt processing because of this error */
+ }
+
+ /* Free the voq ID to the free pool */
+ if (ds_pon_chan == BAL_BCM_SCHED_PON_CHAN_10G)
+ {
+ bal_sw_dpp_qos_free_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_10g, &p_service_cfg->ds_qos.voq_flow_id);
+ }
+ else
+ {
+ bal_sw_dpp_qos_free_flow_id(&gp_bal_bcm_qos_cfg->flow_id_pool_1g, &p_service_cfg->ds_qos.voq_flow_id);
+ }
+}
+
+/**
+ * @brief Clear statistics for a VOQ
+ *
+ * This function is used to clear VOQ counters
+ *
+ * @param unit SDK unit number
+ * @param gport VOQ gport PON port number
+ *
+ */
+void bal_sw_dpp_qos_clear_voq_stats(int unit, bcm_gport_t gport)
+{
+ int cosq;
+
+ /* Clear all VOQ counters for the VOQ group */
+ for (cosq = 0; cosq < BAL_BCM_QOS_QUEUES_PER_LLID; cosq++)
+ {
+ bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportReceivedBytes, 0);
+ bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportReceivedPkts, 0);
+ bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportEnqueuedBytes, 0);
+ bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportEnqueuedPkts, 0);
+ bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportDroppedBytes, 0);
+ bcm_cosq_gport_stat_set(unit, gport, cosq, bcmCosqGportDroppedPkts, 0);
+ }
+}
+
+/**
+ * @brief Display the qos configuration for each on the console (stdout)
+ */
+void bal_sw_dpp_print_all_port_qos(int unit)
+{
+ bal_sw_dpp_port_qos_cfg *p_port_qos = NULL;
+ uint8_t port_num;
+ uint8_t pon_chan;
+ bcm_gport_t e2e_pon_gport;
+ bcm_gport_t e2e_parent_gport;
+ uint32_t min, flags;
+ uint32_t bandwidth;
+ int32_t max_burst;
+ int32_t mode;
+ int32_t weight;
+ uint8_t wfq_lvl;
+
+ /* Display header */
+ printf("Port\\Chan\tgport\t\tRate (kbps)\tMaxBurst (bytes)\tWeight\n");
+ printf("---------\t-----\t\t-----------\t----------------\t------\n");
+
+ for (port_num=BAL_PON_PORT_START; port_num<=BAL_PON_PORT_END; port_num++)
+ {
+ /* Display Port info */
+
+
+ BCM_COSQ_GPORT_E2E_PORT_SET(e2e_pon_gport, port_num);
+
+ if (BCM_E_NONE == bcm_fabric_port_get(unit,
+ e2e_pon_gport,
+ 0,
+ &e2e_parent_gport))
+ {
+ bandwidth = 0;
+ max_burst = 0;
+ weight = 0;
+
+ bcm_cosq_gport_bandwidth_get(unit,
+ e2e_parent_gport,
+ 0,
+ &min,
+ &bandwidth,
+ &flags);
+
+ printf("Port %u\t0x%08X\t%11u\t%16d\t%6d\n",
+ port_num,
+ 0,
+ bandwidth,
+ 0,
+ 0);
+
+ }
+
+ /* Display PON channel configuration */
+ for (pon_chan = 0; pon_chan < BAL_BCM_SCHED_PON_CHAN_NUM; pon_chan++)
+ {
+ p_port_qos = &gp_bal_bcm_qos_cfg->pon[port_num][pon_chan];
+
+ bandwidth = 0;
+ max_burst = 0;
+ weight = 0;
+
+ /* Bandwidth (rate) */
+ bcm_cosq_gport_bandwidth_get(unit,
+ p_port_qos->pon_chan_scheduler,
+ 0,
+ 0,
+ &bandwidth,
+ 0);
+
+ /* Max Burst */
+ bcm_cosq_control_get(unit,
+ p_port_qos->pon_chan_scheduler,
+ 0,
+ bcmCosqControlBandwidthBurstMax,
+ &max_burst);
+
+ printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
+ (pon_chan == BAL_BCM_SCHED_PON_CHAN_10G) ? "10G" : "1G",
+ p_port_qos->pon_chan_scheduler,
+ bandwidth,
+ max_burst,
+ weight);
+
+ printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
+ "MIN",
+ p_port_qos->pon_chan_scheduler,
+ 0,
+ 0,
+ 0);
+
+ if (p_port_qos->sched_type == BAL_BCM_SCHED_TYPE_SP)
+ {
+ printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
+ " MAX (SP)",
+ p_port_qos->sp_scheduler,
+ 0,
+ 0,
+ 0);
+ }
+ else
+ {
+ printf("%9s\t0x%08X\t%11u\t%16d\t%6d\n",
+ " MAX (WFQ)",
+ 0,
+ 0,
+ 0,
+ 0);
+
+ printf(" WFQ weight [");
+ for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ bcm_cosq_gport_sched_get(unit,
+ p_port_qos->wfq_scheduler[wfq_lvl],
+ 0,
+ &mode,
+ &weight);
+
+ printf("w%u=%u(%u)", wfq_lvl, p_port_qos->pon_chan_weight_cfg[wfq_lvl], weight);
+
+ if (wfq_lvl != BAL_BCM_SCHED_WFQ_PRI_NUM - 1)
+ {
+ printf(", ");
+ }
+ }
+ printf("]\n");
+
+ printf(" WFQ gports [");
+ for (wfq_lvl=0; wfq_lvl<BAL_BCM_SCHED_WFQ_PRI_NUM; wfq_lvl++)
+ {
+ printf("w%u=0x%08X", wfq_lvl, p_port_qos->wfq_scheduler[wfq_lvl]);
+
+ if (wfq_lvl != BAL_BCM_SCHED_WFQ_PRI_NUM - 1)
+ {
+ printf(", ");
+ }
+ }
+ printf("]\n");
+ }
+ }
+
+ printf("\n");
+ }
+}
+
+/**
+ * @brief Display the Flow/VOQ ID pool information
+ */
+void bal_sw_dpp_qos_print_flowid_pool(int unit)
+{
+ bal_sw_dpp_qos_flowid_pool_entry *p_pool_entry = NULL;
+ uint8_t count, free_count;
+ int sdkVal;
+
+ printf("\nvoq ID Information:\n");
+ printf(" Min 10G voq ID = %u\n", DEFAULT_QOS_VOQ_BASE_10G);
+ printf(" Max 10G voq ID = %u\n", DEFAULT_QOS_VOQ_MAX_10G);
+ printf(" Min 1G voq ID = %u\n", DEFAULT_QOS_VOQ_BASE_1G);
+ printf(" Max 1G voq ID = %u\n", DEFAULT_QOS_VOQ_MAX_1G);
+ bcm_fabric_control_get(unit, bcmFabricQueueMin, &sdkVal);
+ printf(" Min VOQ ID = %d\n", sdkVal);
+ bcm_fabric_control_get(unit ,bcmFabricQueueMax, &sdkVal);
+ printf(" Max VOQ ID = %d\n", sdkVal);
+
+ printf("\n10G voq ID Table Info:\n");
+ printf(" next_flow_id_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_10g.next_flow_id_value);
+ printf(" max_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_10g.max_value);
+ printf(" Free 10g voq IDs = ");
+
+ printf(" ");
+ count = 0;
+ free_count = 0;
+ TAILQ_FOREACH(p_pool_entry, &gp_bal_bcm_qos_cfg->flow_id_pool_10g.free_table, entry)
+ {
+ printf("%d, ", p_pool_entry->flow_id);
+
+ if (count < 15)
+ {
+ count++;
+ }
+ else
+ {
+ printf("\n ");
+ count = 0;
+ }
+ free_count++;
+ }
+ printf("\n");
+ printf(" Number of Free 10g voq IDs = %d\n", free_count);
+
+ printf("\n1G voq ID Table Info:\n");
+ printf(" next_flow_id_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_1g.next_flow_id_value);
+ printf(" max_value = %u\n", gp_bal_bcm_qos_cfg->flow_id_pool_1g.max_value);
+ printf(" Free 1g voq IDs = ");
+
+ printf(" ");
+ count = 0;
+ free_count = 0;
+ TAILQ_FOREACH(p_pool_entry, &gp_bal_bcm_qos_cfg->flow_id_pool_1g.free_table, entry)
+ {
+ printf("%d, ", p_pool_entry->flow_id);
+
+ if (count < 15)
+ {
+ count++;
+ }
+ else
+ {
+ printf("\n ");
+ count = 0;
+ }
+ free_count++;
+ }
+ printf("\n");
+ printf(" Number of Free 1g voq IDs = %d\n", free_count);
+}
+
+#endif /* TEST_SW_UTIL_LOOPBACK */
+
+/*@}*/
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_qos.h b/bal_release/src/core/util/switch/dpp/bal_dpp_qos.h
new file mode 100644
index 0000000..28c7e36
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_qos.h
@@ -0,0 +1,458 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_qos.h
+ * @brief BAL Switch Util QoS configuration API
+ *
+ * This include file contains the data structures and API for
+ * configuring and managing Quality of Service (QoS) for services on
+ * DPP (DUNE Packet Processor).
+ *
+ *
+ */
+
+/*@{*/
+
+#ifndef _BAL_DPP_QOS_H_
+#define _BAL_DPP_QOS_H_
+
+/* --- project includes --- */
+
+#include "flow_fsm.h"
+
+/* --- local static constants ---*/
+
+/**
+ * @brief Value representing 10G in units of kbps
+ */
+#define BAL_BCM_QOS_10G_kbps 10000000
+
+/**
+ * @brief Value representing 2G (Turbo Mode) in units of kbps
+ */
+#define BAL_BCM_QOS_2G_kbps 2000000
+
+/**
+ * @brief Value representing 1G in units of kbps
+ */
+#define BAL_BCM_QOS_1G_kbps 1000000
+
+/**
+ * @brief Scheduler weight for 10G port scheduler
+ */
+#define BAL_BCM_SCHED_WEIGHT_10G 10
+
+/**
+ * @brief Scheduler weight for 1G port scheduler when Turbo Mode is enabled
+ */
+#define BAL_BCM_SCHED_WEIGHT_2G 2
+
+/**
+ * @brief Scheduler weight for 1G port scheduler (when Turbo Mode is disabled)
+ */
+#define BAL_BCM_SCHED_WEIGHT_1G 1
+
+/**
+ * @brief Scheduler weight used for MIN Rate schedulers
+ */
+#define BAL_BCM_SCHED_WEIGHT_MIN_RATE 1
+
+/**
+ * @brief Scheduler weight used for MAX Rate schedulers
+ */
+#define BAL_BCM_SCHED_WEIGHT_MAX_RATE 1
+
+/**
+ * @brief Number of PON port schedulers
+ */
+#define BAL_BCM_QOS_NUM_PON_PORTS 16
+
+/**
+ * @brief PON port Max value as defined in config.bcm
+ */
+#define BAL_BCM_MAX_PON_NUM 16
+
+/**
+ * @brief Number of queues per PON Link (LLID)
+ */
+#define BAL_BCM_QOS_QUEUES_PER_LLID 4
+
+/**
+ * @brief Default CoS level for untagged frames for 10G queues
+ */
+#define BAL_BCM_QOS_UNTAGGED_DEFAULT_COS_10G 0
+
+/**
+ * @brief Default CoS level for untagged frames for 1G queues
+ */
+#define BAL_BCM_QOS_UNTAGGED_DEFAULT_COS_1G 4
+
+/**
+ * @brief Size of ICT and Shared Vlan tag overhead (in bytes)
+ */
+#define BAL_BCM_QOS_SINGLE_VLAN_TAG_HDR_SIZE 4
+
+/**
+ * @brief Base value for VOQ IDs assigned to the 1G channel
+ *
+ * All VOQ IDs configured on the 1G channel are configured with an
+ * ID value of 0x4000 (16384) and larger.
+ */
+#define BAL_BCM_QOS_VOQ_ID_1G_BASE 0x4000
+
+/**
+ * @brief WFQ maximum value for a weight
+ */
+#define BAL_BCM_SCHED_WFQ_MAX_WEIGHT 4096
+
+/**
+ * @brief Number of WFQ scheduling priority levels
+ */
+#define BAL_BCM_SCHED_WFQ_PRI_NUM 8
+
+/**
+ * @brief Default rate for PON port shaper in kbps (12.5Gbps)
+ */
+#define BAL_BCM_QOS_DEFAULT_PORT_RATE 12500000
+
+/**
+ * @brief Default rate for 10G PON channel shaper in kbps (10.25Gbps)
+ *
+ * The extra 0.25 Gbps allows for some overhead (flow control frames, etc.)
+ */
+#define BAL_BCM_QOS_DEFAULT_10G_CHAN_RATE 10250000
+
+/**
+ * @brief Default rate for 1G PON channel shaper in kbps (2.25Gbps)
+ *
+ * This is set to 2G to allow for Turbo Mode configurations.
+ *
+ * The extra 0.25 Gbps allows for some overhead (flow control frames, etc.)
+ */
+#define BAL_BCM_QOS_DEFAULT_1G_CHAN_RATE 2250000
+
+/**
+ * @brief Credit adjustment to account for scheduler overhead (percentage)
+ *
+ * The adjustment is five percent based on the recommendation from the
+ * Dune team.
+ */
+#define BAL_BCM_QOS_CREDIT_RATE_ADJ 0.05
+
+/**
+ * @brief Shaper adjustment to account for scheduler overhead (percentage)
+ *
+ * The adjustment is one percent based on the recommendation from the
+ * Dune team.
+ */
+#define BAL_BCM_QOS_SHAPER_RATE_ADJ 0.01
+
+/**
+ * @brief Default maximum bust size for PON port shaper in bytes (0 = disabled)
+ */
+#define BAL_BCM_QOS_DEFAULT_MAX_BURST 0
+
+/**
+ * @brief PFC flow control priority value for the 10G channel
+ */
+#define BAL_BCM_QOS_10G_CHAN_PFC 0
+
+/**
+ * @brief PFC flow control priority value for the 1G channel
+ */
+#define BAL_BCM_QOS_1G_CHAN_PFC 1
+
+/**
+ * @brief First logical PON port number
+ */
+#define BAL_PON_PORT_START 0
+
+/**
+ * @brief Last logical PON port number
+ */
+#define BAL_PON_PORT_END 7
+
+/**
+ * @brief The total number of PON ports
+ */
+#define NUM_PON_PORTS (BAL_PON_PORT_END - BAL_PON_PORT_START + 1)
+
+/**
+ * @brief Default DPP header size used by scheduler and rate
+ * calculations.
+ */
+#define DEFAULT_QOS_DPP_PKT_HDR_SIZE 19 /* bytes */
+
+/**
+ * @brief Size of the Dune PP header used to report the Flow ID (for
+ * QoS) in packets trapped to the CPU.
+ */
+#define BAL_BCM_DPP_FLOWID_HDR_SIZE 5
+
+/**
+ * @brief Size of ICT and Shared Vlan tag overhead (in bytes)
+ */
+#define BAL_BCM_QOS_SINGLE_VLAN_TAG_HDR_SIZE 4
+
+
+/**
+ * @brief Default VOQ Identifier Base Value for 10G flows
+ *
+ * 10G VOQ/Flow IDs can range from 3000..16383. This means the blocks
+ * will be allocated in groups of four as follows.
+ *
+ * blk 1 = 3000, 3001, 3002, 3003
+ * blk 2 = 3004, 3005, 3006, 3007
+ * ...
+ * blk last = 16380, 16381, 16382, 16383
+ *
+ * This means that the last ID used to allocate a 10G VOQ group will
+ * be 16380.
+ *
+ * VOQ/flow IDs start at 3000 because the SDK assigns ID values
+ * between 0..2000+ to port queues.
+ */
+#define DEFAULT_QOS_VOQ_BASE_10G 3000
+
+/**
+ * @brief Default VOQ Identifier Maximum Value for 10G flows
+ *
+ * The last available value for 10G flows is 16384 - 4.
+ */
+#define DEFAULT_QOS_VOQ_MAX_10G 16380
+
+/**
+ * @brief Default VOQ Identifier Base Value for 1G flows
+ *
+ * 1G VOQ/Flow IDs can range from 16384..32767. This means the blocks
+ * will be allocated in groups of four as follows.
+ *
+ * blk 1 = 16384, 16385, 16386, 16387
+ * blk 2 = 16388, 16389, 16390, 16392
+ * ...
+ * blk last = 32764, 32765, 32766, 32767
+ *
+ * This means that the last ID used to allocate a 1G VOQ group will be
+ * 32764.
+ */
+#define DEFAULT_QOS_VOQ_BASE_1G 16384
+
+/**
+ * @brief Default VOQ Identifier Maximum Value for 1G flows
+ *
+ * The last available value for 1G flows is 32768 - 4.
+ */
+#define DEFAULT_QOS_VOQ_MAX_1G 32764
+
+/**
+ * @brief Get the PP port number for the specified PON port and
+ * channel (10G vs. 1G)
+ */
+#define BAL_BCM_GET_PP_PORT(pon, chan) ((pon) + (NUM_PON_PORTS * (chan)))
+
+/**
+ * @brief PON channel (a.k.a speed, 10G vs. 1G)
+ *
+ * The 1G PON channel value is also used to represent 2G Turbo Mode
+ * when enabled.
+ */
+typedef enum bal_sw_dpp_qos_sched_pon_chan
+{
+ BAL_BCM_SCHED_PON_CHAN_10G = 0, /**< 10G PON channel */
+ BAL_BCM_SCHED_PON_CHAN_1G = 1, /**< 1G PON channel */
+ BAL_BCM_SCHED_PON_CHAN_NUM
+} bal_sw_dpp_qos_sched_pon_chan;
+
+/**
+ * @brief SLA Type (MIN vs. MAX)
+ */
+typedef enum bal_sw_dpp_qos_sched_sla_type
+{
+ BAL_BCM_SCHED_SLA_MIN_RATE = 0, /**< MIN Rate */
+ BAL_BCM_SCHED_SLA_MAX_RATE = 1, /**< MAX Rate */
+ BAL_BCM_SCHED_SLA_TYPE_NUM
+} bal_sw_dpp_qos_sched_sla_type;
+
+/**
+ * @brief Scheduling Type
+ */
+typedef enum bal_sw_dpp_qos_sched_type
+{
+ BAL_BCM_SCHED_TYPE_SP = 0, /**< Strict priority scheduling */
+ BAL_BCM_SCHED_TYPE_WFQ = 1, /**< Weighted Fair Queuing */
+ BAL_BCM_SCHED_TYPE_NUM
+} bal_sw_dpp_qos_sched_type;
+
+/**
+ * @brief SLA scheduler configuration
+ */
+typedef struct bal_sw_dpp_qos_sched_sla
+{
+ bcm_gport_t scheduler_gport; /**< Scheduler object gport*/
+ bcm_gport_t parent_gport; /**< Parent scheduler gport */
+ uint32_t rate; /**< Rate (or bandwidth) in Kbps */
+ uint32_t burst; /**< Max burst in Kbits */
+ uint8_t traffic_priority; /**< Traffic priority */
+} bal_sw_dpp_qos_sched_sla;
+
+/**
+ * @brief QoS configuration for a PON Link (LLID)
+ */
+typedef struct bal_sw_dpp_llid_qos
+{
+ bal_sw_dpp_qos_sched_pon_chan pon_chan; /**< PON Channel (or speed) the link is connected to */
+ bal_sw_dpp_qos_sched_sla min; /**< MIN Rate configuration */
+ bal_sw_dpp_qos_sched_sla max; /**< MAX Rate configuration */
+ bcm_gport_t voq_connector_gport; /**< VOQ Connector gport */
+ bcm_gport_t voq_gport; /**< VOQ gport */
+ int voq_flow_id; /**< VOQ Flow ID */
+ int voq_id; /**< VOQ ID */
+} bal_sw_dpp_llid_qos;
+
+/**
+ * @brief QoS configuration for a channelized PON port
+ */
+typedef struct bal_sw_dpp_port_qos_cfg
+{
+ bcm_gport_t mod_gport; /**< MOD port for a channelized PON interface */
+ bal_sw_dpp_qos_sched_type sched_type; /**< Scheduling type used on the PON channel (SP vs. WFQ) */
+ bcm_gport_t pon_chan_scheduler; /**< PON channel scheduler */
+ bcm_gport_t sp_scheduler; /**< Strict Priority scheduler for MAX rates (EIRs) */
+ bcm_gport_t wfq_scheduler[BAL_BCM_SCHED_WFQ_PRI_NUM]; /**< WFQ+FQ schedulers for MAX rates (EIRs) */
+ int32_t pon_chan_weight_cfg[BAL_BCM_SCHED_WFQ_PRI_NUM]; /**< Weight configuration for WFQ scheduler */
+} bal_sw_dpp_port_qos_cfg;
+
+/**
+ * @brief Flow/VOQ ID Pool Entry
+ */
+typedef struct bal_sw_dpp_qos_flowid_pool_entry
+{
+ uint32_t flow_id; /**< Flow/VOQ ID value */
+ TAILQ_ENTRY(bal_sw_dpp_qos_flowid_pool_entry) entry; /**< Link into the pool table */
+} bal_sw_dpp_qos_flowid_pool_entry;
+
+/**
+ * @brief Flow/VOQ ID resource pool
+ */
+typedef struct bal_sw_dpp_qos_flowid_pool
+{
+ uint32_t next_flow_id_value; /**< Next flow ID to be allocated */
+ uint32_t max_value; /**< Maximum value for the flow IDs in this pool */
+ TAILQ_HEAD(bal_sw_dpp_qos_flowid_pool_free_head, bal_sw_dpp_qos_flowid_pool_entry) free_table; /**< Flow/VOQ ID free pool */
+} bal_sw_dpp_qos_flowid_pool;
+
+/**
+ * @brief DML BCM APP QoS configuration context definition
+ */
+typedef struct bal_sw_qos_cfg
+{
+ int32_t mod_id; /**< Module ID for this ARAD device */
+ int32_t qos_port_map_id; /**< QoS Port Map Identifier */
+ bal_sw_dpp_port_qos_cfg pon[BAL_BCM_QOS_NUM_PON_PORTS][BAL_BCM_SCHED_PON_CHAN_NUM]; /**< DS QoS configuration for channelized PON ports */
+ bal_sw_dpp_qos_flowid_pool flow_id_pool_10g; /**< Flow/VOQ ID resource pool for 10G flows */
+ bal_sw_dpp_qos_flowid_pool flow_id_pool_1g; /**< Flow/VOQ ID resource pool for 1G flows */
+ int num_channels_per_pon;
+} bal_sw_qos_cfg;
+
+/**
+ * @brief WFQ scheduling configuration
+ *
+ * This structure is used to configure weight values per scheduler
+ * level (i.e., DOCSIS Traffic Priority). The range of weight values
+ * is 0:4K, where values 1:4K are used for WFQ scheduling and a value
+ * of '0' is used for strict priority.
+ */
+typedef struct bal_sw_dpp_qos_wfq_cfg
+{
+ uint32_t weights[BAL_BCM_SCHED_WFQ_PRI_NUM];
+} bal_sw_dpp_qos_wfq_cfg;
+
+extern bal_sw_qos_cfg *gp_bal_bcm_qos_cfg;
+
+/**
+ * @brief Max Number of NNI ports
+ */
+#define BAL_BCM_QOS_NUM_NNI_PORTS 16
+
+/**
+ * @brief Service Configuration Entry Type
+ *
+ * The type of service configuration that the DmlBcmServiceCfgT entry
+ * represents.
+ */
+typedef enum bal_sw_service_type
+{
+ BAL_BCM_SVC_TYPE_NONE, /**< None/uninitialized */
+ BAL_BCM_SVC_TYPE_ICT, /**< Intra-chassis Tagged */
+ BAL_BCM_SVC_TYPE_IP, /**< IP(HSD) */
+ BAL_BCM_SVC_TYPE_PB, /**< MEF Provider Bridging (VLAN tagged) */
+ BAL_BCM_SVC_TYPE_SHVLAN,/**< Shared VLAN */
+ BAL_BCM_SVC_TYPE_LAST /**< Number of bal_sw_service_type_t values */
+} bal_sw_service_type;
+
+/* --- forward declarations --- */
+
+typedef struct bal_sw_dpp_qos_service_cfg
+{
+ uint32_t bal_flow_id;
+ bcm_port_t pon_port; /* logical port number from bal flow config */
+ uint32_t num_nni_gport;
+ bcm_gport_t nni_gport[BAL_BCM_QOS_NUM_NNI_PORTS];
+ uint32_t tunnel_id;
+ bal_sw_dpp_llid_qos ds_qos;
+ bal_sw_service_type service_type;
+} bal_sw_dpp_qos_service_cfg;
+
+
+/* --- function prototypes --- */
+
+bcmos_errno bal_sw_dpp_qos_init(int unit, bal_swapp_port_map_indx pon_mode);
+void bal_sw_dpp_qos_cleanup(int unit);
+bcmos_errno bal_sw_dpp_port_qos_init(int unit, bcm_port_t pon_port, bal_sw_dpp_qos_sched_pon_chan pon_chan);
+void bal_sw_dpp_port_qos_cleanup(int unit, bcm_port_t pon_port, bal_sw_dpp_qos_sched_pon_chan pon_chan);
+bcmos_errno bal_sw_dpp_qos_set_port_bandwidth(int unit, bcm_port_t pon_port, uint32_t bandwidth, uint32_t max_burst);
+bcmos_errno bal_sw_dpp_qos_set_portchan_bandwidth(int unit, bcm_port_t pon_port, bal_sw_dpp_qos_sched_pon_chan pon_chan,
+ uint32_t bandwidth, uint32_t max_burst);
+bcmos_errno bal_sw_dpp_qos_set_ponchan_wfq_cfg(int unit, bcm_port_t pon_port,
+ bal_sw_dpp_qos_sched_pon_chan pon_chan, bal_sw_dpp_qos_wfq_cfg *p_wfq_cfg);
+bcmos_errno bal_sw_dpp_qos_set_llid_bandwidth(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg,
+ bal_sw_dpp_qos_sched_sla_type sla_type, uint32_t bandwidth, uint32_t max_burst);
+bcmos_errno bal_sw_dpp_llid_qos_config(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg_entry);
+bcmos_errno bal_sw_dpp_llid_set_qos_port_map(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg_entry);
+void bal_sw_dpp_llid_qos_cleanup(int unit, bal_sw_dpp_qos_service_cfg *p_service_cfg_entry);
+void bal_sw_dpp_qos_clear_voq_stats(int unit, bcm_gport_t gport);
+void bal_sw_dpp_print_all_port_qos(int unit);
+void bal_sw_dpp_qos_print_flowid_pool(int unit);
+
+#endif /* #ifndef _BAL_DPP_QOS_H_ */
+
+/*@}*/
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_qos_map.c b/bal_release/src/core/util/switch/dpp/bal_dpp_qos_map.c
new file mode 100644
index 0000000..6614b7c
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_qos_map.c
@@ -0,0 +1,236 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_qos_map.c
+ * @brief BAL Switch Util QoS map management API
+ *
+ * This file contains the data structures and functions for
+ * configuring and managing the pcp bits translation services for
+ * DUNE Pack Processor (DPP).
+ *
+ * The pcp translation service is accomplished using ING ingress vlan translation API
+ * The API required a Qos map table for pcp translatin on a LIF.
+ * This file defines 15 pre-map tables for all known use cases.
+ *
+ * A set of utilities API are included for callers to determine which table to use
+ *
+ * ********************************************************************************
+ *
+ */
+
+/*@{*/
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+#include <stdint.h>
+
+#include "bcm_dev_log.h"
+#include "bcmos_errno.h"
+#include "bal_dpp_qos_map.h"
+
+#include "bal_switch_util.h" /* for definition of log_id_sw_util */
+
+#include "bcm/error.h"
+#include "bcm/qos.h"
+
+#define BAL_BCM_PCP_MAP_NUM 15
+#define BAL_BCM_PCP_MAP_ENTRIES 8
+#define BAL_BCM_MAX_PCP_VALUE 7
+#define BAL_BCM_FIXED_PCP_MAP_NUM 8
+
+
+const int g_bal_bcm_qos_pcp_map[BAL_BCM_PCP_MAP_NUM][BAL_BCM_PCP_MAP_ENTRIES] =
+{
+ {0, 0, 0, 0, 0, 0, 0, 0}, /* 0-7 --> 0 */
+ {1, 1, 1, 1, 1, 1, 1, 1}, /* 0-7 --> 1 */
+ {2, 2, 2, 2, 2, 2, 2, 2}, /* 0-7 --> 2 */
+ {3, 3, 3, 3, 3, 3, 3, 3}, /* 0-7 --> 3 */
+ {4, 4, 4, 4, 4, 4, 4, 4}, /* 0-7 --> 4 */
+ {5, 5, 5, 5, 5, 5, 5, 5}, /* 0-7 --> 5 */
+ {6, 6, 6, 6, 6, 6, 6, 6}, /* 0-7 --> 6 */
+ {7, 7, 7, 7, 7, 7, 7, 7}, /* 0-7 --> 7 */
+ {1, 2, 3, 4, 5, 6, 7, 0}, /* 0-6 --> 1-7, 7 ->0 offset = 1 or -7 */
+ {2, 3, 4, 5, 6, 7, 0, 1}, /* 0-5 --> 2-7, 6-7->0-1 offset = 2 or -6 */
+ {3, 4, 5, 6, 7, 0, 1, 2}, /* 0-4 --> 3-7, 5-7->0-2 offset = 3 or -5 */
+ {4, 5, 6, 7, 0, 1, 2, 3}, /* 0-3 --> 4-7, 4-7->0-3 offset = 4 or -4 */
+ {5, 6, 7, 0, 1, 2, 3, 4}, /* 0-2 --> 5-7, 3-7->0-4 offset = 5 or -3 */
+ {6, 7, 0, 1, 2, 3, 4, 5}, /* 0-1 --> 6-7, 2-7->0-5 offset = 6 or -2 */
+ {7, 0, 1, 2, 3, 4, 5, 6}, /* 0 --> 7, 1-7->0-6 offset = 7 or -1 */
+};
+
+static int g_bal_bcm_pcp_remark_map_id[BAL_BCM_PCP_MAP_NUM];
+
+/**************************************************************************/
+/**
+ * @brief Create the PCP remark mapping tables
+ *
+ * This function creates the mapping from PCP bits in the
+ * frames received by DPP to the internal priority in
+ * DPP. The created map id are used in the ingress vlan translation API
+ * to perform PCP bits replacement.
+ *
+ *
+ * @param unit SDK unit number
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_pcp_remark_maps_init(int unit)
+{
+ bcm_error_t sdk_rc = BCM_E_NONE;
+ bcm_qos_map_t l2_in_map;
+ int map_id, pcp;
+ int32_t qos_map_id;
+
+
+ for(map_id=0; map_id < BAL_BCM_PCP_MAP_NUM; map_id++)
+ {
+ /* in case anything goes wrong */
+ g_bal_bcm_pcp_remark_map_id[map_id] = BAL_BCM_INVALID_PCP_MAP_ID;
+
+ /* Create a map object */
+ sdk_rc = bcm_qos_map_create(unit, BCM_QOS_MAP_INGRESS| BCM_QOS_MAP_L2_VLAN_PCP, &qos_map_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "bcm_qos_map_create failed with %s\n",
+ bcm_errmsg(sdk_rc));
+
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* Create a mapping for each PCP bits value. */
+ for (pcp = 0; pcp < BAL_BCM_PCP_MAP_ENTRIES; pcp++)
+ {
+ bcm_qos_map_t_init(&l2_in_map);
+
+ /* Ingress PCP/CoS value */
+ l2_in_map.pkt_pri = g_bal_bcm_qos_pcp_map[map_id][pcp];
+
+ /* Set internal priority for this ingress pri */
+ l2_in_map.int_pri = pcp;
+
+ /* Set color for this ingress Priority */
+ l2_in_map.color = bcmColorGreen;
+
+ sdk_rc = bcm_qos_map_add(unit, BCM_QOS_MAP_L2_OUTER_TAG|BCM_QOS_MAP_L2|BCM_QOS_MAP_L2_VLAN_PCP, &l2_in_map, qos_map_id);
+ if (sdk_rc != BCM_E_NONE)
+ {
+ /* Error */
+ BCM_LOG(ERROR, log_id_sw_util,
+ "bcm_qos_map_add failed with %s, for pcp %d\n",
+ bcm_errmsg(sdk_rc), pcp);
+
+ return BCM_ERR_INTERNAL;
+ }
+
+ }
+
+ g_bal_bcm_pcp_remark_map_id[map_id] = qos_map_id;
+ }
+ return BCM_ERR_OK;
+}
+
+/**************************************************************************/
+/**
+ * @brief Retrieve PCP remark mapping table ID according to the translation
+ *
+ * This function retrieve the pre-created mapping table id associate with
+ * the translation.
+ * The created map id can be used in the ingress vlan translation API
+ * to perform PCP bits replacement.
+ *
+ * @param src_pcp the pcp value that need to be translated, or -1 for DONTCARE
+ * @param dst_pcp the translated pcp value
+ * @param p_map_id pointer for the retrieved id
+ *
+ * @return bcmos_errno
+ *
+ **************************************************************************/
+bcmos_errno bal_sw_dpp_pcp_remark_map_get(int src_pcp, int dst_pcp, int *p_map_id)
+{
+ int offset;
+ unsigned int indx;
+
+ if(dst_pcp < 0 || dst_pcp > BAL_BCM_MAX_PCP_VALUE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): invalid destination pcp = %d\n", __FUNCTION__, dst_pcp);
+ return BCM_ERR_PARM;
+ }
+ /* if source is DONTCARE, i.e map to a fixed PCP, use the first 8 map tables */
+ if(src_pcp == -1)
+ {
+ *p_map_id = g_bal_bcm_pcp_remark_map_id[dst_pcp];
+ }
+ else
+ {
+ if(src_pcp < 0 || src_pcp > BAL_BCM_MAX_PCP_VALUE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): invalid source pcp = %d\n", __FUNCTION__, src_pcp);
+ return BCM_ERR_PARM;
+ }
+ /* find out the offset between the src_pcp and dst_pcp */
+ offset = dst_pcp - src_pcp;
+ if (offset == 0)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): source pcp %d == destination pcp %d\n", __FUNCTION__, src_pcp, dst_pcp);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ if (offset < 0)
+ {
+ /* see comments in the above map tables */
+ offset += BAL_BCM_PCP_MAP_ENTRIES;
+ }
+
+ indx = offset + BAL_BCM_FIXED_PCP_MAP_NUM - 1;
+ if(indx >= BAL_BCM_PCP_MAP_NUM)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ "%s(): something is wrong, invalid map index = %d\n", __FUNCTION__, indx);
+ return BCM_ERR_INTERNAL;
+ }
+ /* index is 0 based */
+ *p_map_id = g_bal_bcm_pcp_remark_map_id[indx];
+
+ }
+
+ BCM_LOG(INFO, log_id_sw_util,
+ "%s(): pbits translate %d -> %d using bal qos map table %d, id 0x%x\n", __FUNCTION__, src_pcp, dst_pcp, indx, *p_map_id);
+ return BCM_ERR_OK;
+}
+
+#endif /* TEST_SW_UTIL_LOOPBACK */
+
+/*@}*/
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_qos_map.h b/bal_release/src/core/util/switch/dpp/bal_dpp_qos_map.h
new file mode 100644
index 0000000..a73e5b5
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_qos_map.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_dpp_qos_map.h
+ *
+ * @brief bal qos map service function header file for DUNE PACKET PROCESSOR
+ *
+ */
+
+#ifndef _BAL_DPP_QOS_MAP_H_
+#define _BAL_DPP_QOS_MAP_H_
+/*@{*/
+
+#include "bcmos_errno.h"
+
+#define BAL_BCM_INVALID_PCP_MAP_ID -1
+
+bcmos_errno bal_sw_dpp_pcp_remark_maps_init(int unit);
+bcmos_errno bal_sw_dpp_pcp_remark_map_get(int src_pcp, int dst_pcp, int *p_map_id);
+
+/*@}*/
+
+#endif /* _BAL_DPP_QOS_MAP_H */
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_vswitch.c b/bal_release/src/core/util/switch/dpp/bal_dpp_vswitch.c
new file mode 100644
index 0000000..d281e1f
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_vswitch.c
@@ -0,0 +1,785 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+ /**
+ * @file bal_dpp_vswitch.c
+ * @brief BAL Switch util helper functions that handle vswitch service requests
+ * @addtogroup sw_util
+ */
+
+/*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include <bal_utils_msg.h>
+#include "bcmos_errno.h"
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <bcm/types.h>
+#include <sal/core/libc.h>
+#ifndef sal_memset
+#define sal_memset memset
+#endif
+#include <bcm/port.h>
+#include <bcm/vlan.h>
+#include <bcm/error.h>
+#include <bcm/vswitch.h>
+
+#include "bal_switch_flow.h"
+#include "bal_dpp_vswitch.h"
+#include "bal_switch_util.h"
+
+/* A local link list to keep trak of virtual switch service */
+TAILQ_HEAD(bal_sw_vsi_list_head, bal_sw_vsi_service) g_swutil_vsi_list;
+
+/**
+ * @brief The vsi list init function prepare a link list to keep track of
+ * vsi service in the switch util
+ *
+ * @return error code
+ */
+bcmos_errno bal_sw_util_vsi_list_init(void)
+{
+ static uint32_t g_vsi_inited = 0;
+ if(g_vsi_inited == 0)
+ {
+ TAILQ_INIT(&g_swutil_vsi_list);
+ g_vsi_inited = 1;
+ }
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The vsi list search function by LIF tag
+ *
+ * @param p_lif_tag a pointer to the packet tag that need to match the entry in the list
+ * @param p_svc_indx a pointer to store the created service tag index within the vsi
+
+ * @return pointer to an element in the list, NULL if failed
+ */
+static bal_sw_vsi_service *bal_sw_util_dpp_vsi_service_get_by_tag(bal_sw_lif_pkt_tag *p_lif_tag, uint32_t *p_svc_indx)
+{
+ bal_sw_vsi_service *p_entry, *p_temp;
+ int lif_match = 0, svc_idx;
+
+ if(p_svc_indx == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "call VSI service get tag with invalid parameter\n");
+ return NULL;
+ }
+
+ /* clear the storage area */
+ *p_svc_indx = 0;
+
+ TAILQ_FOREACH_SAFE(p_entry, &g_swutil_vsi_list, next_service, p_temp)
+ {
+ for(svc_idx = 0; svc_idx < p_entry->num_tag; svc_idx++)
+ {
+ if( p_entry->pkt_tag[svc_idx].type == p_lif_tag->type)
+ {
+ switch (p_lif_tag->type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ if( p_lif_tag->o_vid == p_entry->pkt_tag[svc_idx].o_vid)
+ {
+ lif_match = 1;
+ }
+ break;
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ if( p_lif_tag->o_vid == p_entry->pkt_tag[svc_idx].o_vid && p_lif_tag->i_vid == p_entry->pkt_tag[svc_idx].i_vid)
+ {
+ lif_match = 1;
+ }
+ break;
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ lif_match = 1;
+ break;
+ default:
+ BCM_LOG(ERROR, log_id_sw_util, "Unsupported packet type %d in LIF info\n", p_lif_tag->type);
+ return NULL;
+ }
+ if(lif_match)
+ {
+ if(p_svc_indx)
+ {
+ *p_svc_indx = svc_idx;
+ }
+ return p_entry;
+ }
+ }
+ }
+ }
+
+ /* if reach the end of the list, TAILQ_FOREACH_SAFE set the p_entry to NULL */
+ return NULL;
+
+}
+
+/*
+ * @brief The vsi list insert function
+ *
+ * @param entry the vsi element to be added in the link list
+ * @return error code
+*/
+static bal_sw_vsi_service *bal_sw_util_vsi_list_insert(bal_sw_vsi_service *p_entry)
+{
+ bal_sw_vsi_service *p_new_entry;
+
+ p_new_entry = bcmos_calloc(sizeof(bal_sw_vsi_service));
+ if(NULL == p_new_entry)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "VSI list insert out of memory\n");
+ return NULL;
+ }
+ *p_new_entry = *p_entry;
+ TAILQ_INSERT_TAIL(&g_swutil_vsi_list, p_new_entry, next_service);
+ return p_new_entry;
+}
+
+/*
+ * @brief The vsi list remove function
+ *
+ * @param p_entry Pointer to the vsi element in the link list result from the search functions
+ * @return error code
+*/
+static bcmos_errno bal_sw_util_vsi_list_remove(bal_sw_vsi_service *p_entry)
+{
+ TAILQ_REMOVE(&g_swutil_vsi_list, p_entry, next_service);
+ bcmos_free(p_entry);
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The vsi create function create a virtual switch service that contains ingress LIF
+ * and virtual switch. This service can later be connected to multiple egress LIF of multiple FLOWs.
+ * The function use the source port and vid information in the bcmbal_flow_cfg as input
+ * The pointer of the created vsi will be returned
+ * Since a vsi can provide multiple srevices, the index to the created service tag is return here
+ *
+ * @param unit switch device id
+ * @param p_flow a pointer to the flow definition which the created service will be based on
+ * @param p_svc_indx a pointer to store the created service tag index within the vsi
+ *
+ * @return pointer to the vsi service list entry, NULL if operation failed
+ */
+
+bal_sw_vsi_service *bal_sw_util_dpp_vsi_service_create(int unit, bcmbal_flow_cfg *p_flow, uint32_t *p_svc_indx)
+{
+ int rv;
+ bal_sw_lif_pkt_tag svc_pkt_tag = {0};
+ bal_sw_vsi_service *p_vsi_service, vsi_svc_elm;
+ bcm_vlan_t vsi;
+ int multicast_id, flags;
+
+ /* p_flow can be NULL when create vswitch for multicast group, service tag will be added when multicast flow is created */
+ if (p_flow == NULL)
+ {
+ BCM_LOG(INFO, log_id_sw_util, "create vsi service with no service tag \n");
+ p_vsi_service = NULL;
+ }
+ else
+ {
+ /* find out if the vsi service already exist */
+ svc_pkt_tag.type = p_flow->data.classifier.pkt_tag_type;
+ svc_pkt_tag.o_vid = p_flow->data.classifier.o_vid;
+ svc_pkt_tag.i_vid = p_flow->data.classifier.i_vid;
+ p_vsi_service = bal_sw_util_dpp_vsi_service_get_by_tag(&svc_pkt_tag, p_svc_indx);
+ }
+
+ /* if no service, create one */
+ if(p_vsi_service == NULL)
+ {
+ /* initialize link list vsi element */
+ memset(&vsi_svc_elm, 0, sizeof (bal_sw_vsi_service));
+ /* if flow (service tag) is specified, fill in the basic info, since it is new, add it to the first tag */
+ if(p_flow)
+ {
+ vsi_svc_elm.pkt_tag[0] = svc_pkt_tag;
+ vsi_svc_elm.num_tag = 1;
+ }
+
+ rv = bcm_vswitch_create(unit, &vsi);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "bcm_vswitch_create failed %d \n", rv);
+ return NULL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, " vswitch 0x%x created\n", vsi);
+ }
+ vsi_svc_elm.vswitch = vsi;
+ /* create two multicast groups (a.k.a. flooding group), one for upstream and one for downstream
+ clean up first, it is OK there is nothing to destroy */
+
+ /* Create the multicast group used for upstream flooding
+ * (PON-->NNI). For the upstream mcast group, the QAX hardware
+ * requires the ID to be set to a value equal to the VSI ID
+ * created above.
+ */
+ multicast_id = vsi + BAL_DPP_US_FLOOD_OFFSET;
+ rv = bcm_multicast_group_is_free(unit, multicast_id);
+ if (rv == BCM_E_EXISTS)
+ {
+ rv = bcm_multicast_destroy(unit, multicast_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "US: bcm_multicast_destroy 0x%x failed %d \n", multicast_id, rv);
+ bcm_vswitch_destroy(unit, vsi);
+ return NULL;
+ }
+ }
+ /* flags = ingress replication + fixed id + L2 multicast */
+ flags = BCM_MULTICAST_INGRESS_GROUP | BCM_MULTICAST_WITH_ID | BCM_MULTICAST_TYPE_L2;
+ rv = bcm_multicast_create(unit, flags, &multicast_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "US: in bcm_multicast_create 0x%x w ingress failed %d \n", multicast_id, rv);
+ bcm_vswitch_destroy(unit, vsi);
+ return NULL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "US: vswitch flood group 0x%x created\n", multicast_id);
+ }
+ vsi_svc_elm.us_flood_grp_id = multicast_id;
+
+ /* downstream flooding group */
+ multicast_id = vsi + BAL_DPP_DS_FLOOD_OFFSET;
+ rv = bcm_multicast_group_is_free(unit, multicast_id);
+ if (rv == BCM_E_EXISTS)
+ {
+ rv = bcm_multicast_destroy(unit, multicast_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "DS: bcm_multicast_destroy 0x%x failed %d \n", multicast_id, rv);
+ bcm_multicast_destroy(unit, vsi_svc_elm.us_flood_grp_id);
+ bcm_vswitch_destroy(unit, vsi);
+ return NULL;
+ }
+ }
+ flags = BCM_MULTICAST_INGRESS_GROUP | BCM_MULTICAST_WITH_ID | BCM_MULTICAST_TYPE_L2;
+ rv = bcm_multicast_create(unit, flags, &multicast_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "DS: in bcm_multicast_create 0x%x w ingress 2 failed %d \n", multicast_id, rv);
+ bcm_multicast_destroy(unit, vsi_svc_elm.us_flood_grp_id);
+ bcm_vswitch_destroy(unit, vsi);
+ return NULL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "DS: vswitch flood group 0x%x created\n", multicast_id);
+ }
+ vsi_svc_elm.ds_flood_grp_id = multicast_id;
+
+ /* add vsi service to the vsi list */
+ p_vsi_service = bal_sw_util_vsi_list_insert(&vsi_svc_elm);
+ if (p_vsi_service == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "VSI: fail to insert new vsi to the service list\n");
+ bcm_multicast_destroy(unit, vsi_svc_elm.us_flood_grp_id);
+ bcm_multicast_destroy(unit, vsi_svc_elm.ds_flood_grp_id);
+ bcm_vswitch_destroy(unit, vsi_svc_elm.vswitch);
+ return NULL;
+ }
+ p_vsi_service->use_count = 1;
+ }
+ else
+ {
+ p_vsi_service->use_count++;
+ }
+
+ return p_vsi_service;
+}
+
+/**
+ * @brief The vsi destroy function free up Hardare resource of a virtual switch.
+ * It also remove the vsi fromt the service list
+ *
+ * @param unit switch device id
+ * @param p_vsi_svc a pointer to the vsi service
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_vsi_service_destroy(int unit, bal_sw_vsi_service *p_vsi_svc)
+{
+ int rv;
+
+ /* input validation */
+ if (p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "destroy vsi service with invalid parameters \n");
+ return BCM_ERR_PARM;
+ }
+
+ /* only clean up when no more users */
+ if(p_vsi_svc->use_count > 1)
+ {
+ p_vsi_svc->use_count--;
+ return BCM_ERR_OK;
+ }
+
+ /* free up HW resource, continue even if any failed */
+ rv = bcm_multicast_destroy(unit, p_vsi_svc->us_flood_grp_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "bcm_multicast_destroy US 0x%x failed %d \n", p_vsi_svc->us_flood_grp_id, rv);
+ }
+ rv = bcm_multicast_destroy(unit, p_vsi_svc->ds_flood_grp_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "bcm_multicast_destroy DS 0x%x failed %d \n", p_vsi_svc->ds_flood_grp_id, rv);
+ }
+ rv = bcm_vswitch_destroy(unit, p_vsi_svc->vswitch);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "bcm_multicast_destroy vswitch 0x%x failed %d \n", p_vsi_svc->vswitch, rv);
+ }
+
+ /* remove from the service list */
+ rv = bal_sw_util_vsi_list_remove(p_vsi_svc);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "bcm_multicast_destroy VSI entry failed %d \n", rv);
+ }
+
+ return BCM_ERR_OK;
+}
+
+
+/**
+ * @brief The vsi port_find function search a port from the port list of a vsi service entry.
+ *
+ * @param p_vsi_svc a pointer to the vsi service
+ * @param svc_tag_indx an index to the service within the vsi that a port need to be searched
+ * @param port the ingress port that needs to be located
+ * @param idx pointer to a storage where the array index of the found port will be return
+ *
+ * @return error code
+ */
+
+static bcmos_errno bal_sw_util_dpp_vsi_service_port_find(bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx, uint32_t port, uint32_t *idx)
+{
+ int i;
+
+ /* input validation */
+ if (p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "vsi service port find function with invalid parameters \n");
+ return BCM_ERR_PARM;
+ }
+ /* loop through the list */
+ for( i=0; i<p_vsi_svc->pkt_tag[svc_tag_indx].num_port; i++)
+ {
+ if(p_vsi_svc->pkt_tag[svc_tag_indx].port[i].port == port)
+ {
+ break;
+ }
+ }
+ if (i == p_vsi_svc->pkt_tag[svc_tag_indx].num_port)
+ {
+ return BCM_ERR_NOENT;
+ }
+ *idx = i;
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The vsi port_find function search a gport from the port list of a vsi service entry.
+ *
+ * @param p_vsi_svc a pointer to the vsi service
+ * @param svc_tag_indx an index to the service within the vsi that a gport need to be searched
+ * @param gport the ingress gport that needs to be located
+ * @param idx pointer to a storage where the array index of the found port will be return
+ *
+ * @return error code
+ */
+
+static bcmos_errno bal_sw_util_dpp_vsi_service_gport_find(bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx, uint32_t gport, uint32_t *idx)
+{
+ int i;
+
+ /* input validation */
+ if (p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "vsi service port find function with invalid parameters \n");
+ return BCM_ERR_PARM;
+ }
+ /* loop through the list */
+ for( i=0; i<p_vsi_svc->pkt_tag[svc_tag_indx].num_port; i++)
+ {
+ if(p_vsi_svc->pkt_tag[svc_tag_indx].port[i].gport == gport)
+ {
+ break;
+ }
+ }
+ if (i == p_vsi_svc->pkt_tag[svc_tag_indx].num_port)
+ {
+ return BCM_ERR_NOENT;
+ }
+ *idx = i;
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The vsi port_add function add an ingress port to the vsi service.
+ If the port is already in the vsi, just increase the counter
+ If the port is not in the vsi, create a gport and add it to the US flooding group.
+ This allows the US SPEAK_FIRST packets to be forwarded to the network.
+ *
+ * @param unit switch device id
+ * @param p_vsi_svc a pointer to the vsi service
+ * @param svc_tag_indx an index to the service within the vsi that a port need to be added
+ * @param port the ingress port that needs to be added to the vsi service
+ * @param p_gport a valid pointer where the created/existing gport will be returned.
+ * NULL, if caller don't care the gport
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_vsi_service_port_add(int unit, bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx, uint32_t port, int32_t *p_gport)
+{
+ bcm_vlan_port_t vp;
+ uint32_t idx;
+ int ind, rv;
+ int32_t gport;
+ bcmos_errno ret;
+ int port_encap_id;
+
+ /* input validation */
+ if (p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "vsi service port add function with invalid parameters \n");
+ return BCM_ERR_PARM;
+ }
+ /* check if the port already in the vsi */
+ ret = bal_sw_util_dpp_vsi_service_port_find(p_vsi_svc, svc_tag_indx, port, &idx);
+ /* if port already in the vsi, just increase the counter */
+ if(ret == BCM_ERR_OK)
+ {
+ if(p_gport)
+ {
+ *p_gport = p_vsi_svc->pkt_tag[svc_tag_indx].port[idx].gport;
+ }
+ (p_vsi_svc->pkt_tag[svc_tag_indx].port[idx].use_count)++;
+ return BCM_ERR_OK;
+ }
+
+ /* create the LIF */
+ bcm_vlan_port_t_init(&vp);
+ vp.port = port;
+ /* configure frame match according to the service packet tags */
+ switch(p_vsi_svc->pkt_tag[svc_tag_indx].type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_UNTAGGED:
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_VLAN;
+ vp.match_vlan = p_vsi_svc->pkt_tag[svc_tag_indx].o_vid;
+ break;
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ vp.criteria = BCM_VLAN_PORT_MATCH_PORT_VLAN_STACKED;
+ vp.match_vlan = p_vsi_svc->pkt_tag[svc_tag_indx].o_vid;
+ vp.match_inner_vlan = p_vsi_svc->pkt_tag[svc_tag_indx].i_vid;
+ break;
+ default:
+ /* should not reach here */
+ BCM_LOG(ERROR, log_id_sw_util, "VSI: Unsupported packet type %d \n",p_vsi_svc->pkt_tag[svc_tag_indx].type );
+ return BCM_ERR_INTERNAL;
+ break;
+ }
+
+ vp.vsi = 0; /* will be populated when the gport is added to service, using vswitch_port_add */
+ vp.flags = BCM_VLAN_PORT_OUTER_VLAN_PRESERVE | BCM_VLAN_PORT_INNER_VLAN_PRESERVE;
+
+ rv = bcm_vlan_port_create(unit, &vp);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "VSI: bcm_vlan_port_create port %d, failed %d\n", port, rv);
+ return BCM_ERR_INTERNAL;
+ }
+
+ gport = vp.vlan_port_id;
+
+ // add gport to vswitch
+ rv = bcm_vswitch_port_add(unit, p_vsi_svc->vswitch, gport);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "VSI, bcm_vswitch_port_add for port %d failed %d\n", port, rv);
+ bcm_vlan_port_destroy(unit, gport);
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util, "VSI: bcm_vswitch_port_add for port %d, gport 0x%x\n", port, gport);
+ }
+ /* if caller requre for the gport info, return the gport */
+ if(p_gport)
+ {
+ *p_gport = gport;
+ }
+ /* record the gport into the vsi */
+ ind = p_vsi_svc->pkt_tag[svc_tag_indx].num_port;
+ if (ind == MAX_NET_PORT)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "VSI, reach max port allow\n");
+ bcm_vswitch_port_delete(unit, p_vsi_svc->vswitch, gport);
+ bcm_vlan_port_destroy(unit, gport);
+ return BCM_ERR_NORES;
+ }
+ p_vsi_svc->pkt_tag[svc_tag_indx].port[ind].port = port;
+ p_vsi_svc->pkt_tag[svc_tag_indx].port[ind].gport = gport;
+ p_vsi_svc->pkt_tag[svc_tag_indx].port[ind].use_count = 1;
+ p_vsi_svc->pkt_tag[svc_tag_indx].num_port = ++ind;
+
+ ret = BCM_ERR_OK;
+ do
+ {
+ // update flooding group with phy_port/gport as ingress port
+ rv = bcm_multicast_vlan_encap_get(unit, p_vsi_svc->us_flood_grp_id, port, gport, &port_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_multicast_vlan_encap_get for port failed %d\n", rv);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ /* be a member of the upstream flooding group */
+ rv = bcm_multicast_ingress_add(unit, p_vsi_svc->us_flood_grp_id, port, port_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_multicast_ingress_add for port failed %d\n", rv);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+
+ /* now set the type of packets that goes to the downstream flooding group */
+ /* forward unknown unicast */
+ rv = bcm_port_control_set(unit, gport, bcmPortControlFloodUnknownUcastGroup, BAL_DPP_DS_FLOOD_OFFSET);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_control_set ucast for nni failed %d\n", rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* drop unknown multicast */
+ rv = bcm_port_control_set(unit, gport, bcmPortControlFloodUnknownMcastGroup, BCM_GPORT_BLACK_HOLE);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_control_set mcast for nni failed %d\n", rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* forward broadcast */
+ rv = bcm_port_control_set(unit, gport, bcmPortControlFloodBroadcastGroup, BAL_DPP_DS_FLOOD_OFFSET);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_port_control_set bcast for nni failed %d\n", rv);
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }while(0);
+
+ return ret;
+}
+
+/**
+ * @brief The vsi port_rem function remove an ingress port to the vsi service.
+ *
+ * @param unit switch device id
+ * @param p_vsi_svc a pointer to the vsi service
+ * @param svc_tag_indx an index to the service within the vsi that a port need to be removed
+ * @param gport the ingress gport that needs to be removed from the vsi service
+ *
+ * @return error code
+ */
+
+bcmos_errno bal_sw_util_dpp_vsi_service_port_rem(int unit, bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx, uint32_t gport)
+{
+ uint32_t idx;;
+ int port_encap_id, rv, i;
+ bcmos_errno ret = BCM_ERR_OK;
+ int port;
+ /* input validation */
+ if (p_vsi_svc == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "vsi service port rem function with invalid parameters \n");
+ return BCM_ERR_PARM;
+ }
+ /* check if the port in the vsi */
+ ret = bal_sw_util_dpp_vsi_service_gport_find(p_vsi_svc, svc_tag_indx, gport, &idx);
+ if(ret != BCM_ERR_OK)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, vsi service port find for gport %d failed\n", gport);
+ return ret;
+ }
+ /* only remove from the array when no flow reference it */
+ if(p_vsi_svc->pkt_tag[svc_tag_indx].port[idx].use_count > 1)
+ {
+ (p_vsi_svc->pkt_tag[svc_tag_indx].port[idx].use_count)--;
+ return BCM_ERR_OK;
+ }
+
+ port = p_vsi_svc->pkt_tag[svc_tag_indx].port[idx].port;
+
+ /* compact the port list */
+ for(i=idx; i<p_vsi_svc->pkt_tag[svc_tag_indx].num_port-1; i++)
+ {
+ p_vsi_svc->pkt_tag[svc_tag_indx].port[i] = p_vsi_svc->pkt_tag[svc_tag_indx].port[i+1];
+ }
+ memset(&p_vsi_svc->pkt_tag[svc_tag_indx].port[i], 0, sizeof (bal_sw_lif_port));
+
+ (p_vsi_svc->pkt_tag[svc_tag_indx].num_port)--;
+
+ ret = BCM_ERR_OK;
+ do
+ {
+ /* find the encap_id */
+ rv = bcm_multicast_vlan_encap_get(unit, p_vsi_svc->us_flood_grp_id, port, gport, &port_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_multicast_vlan_encap_get for port %d failed %d\n", port, rv);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ /* remove from the upstream flooding group */
+ rv = bcm_multicast_ingress_delete(unit, p_vsi_svc->us_flood_grp_id, port, port_encap_id);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_multicast_ingress_delete for port %d failed %d\n", port, rv);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ rv = bcm_vswitch_port_delete(unit, p_vsi_svc->vswitch, gport);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "Error, bcm_vswitch_port_delete for port %d failed %d\n", port, rv);
+ ret = BCM_ERR_NOENT;
+ break;
+ }
+ rv = bcm_vlan_port_destroy(unit, gport);
+ if (rv != BCM_E_NONE)
+ {
+ BCM_LOG(WARNING, log_id_sw_util, "Error, bcm_vlan_port_destroy for port %d failed %d\n", port, rv);
+ /* Likely a bug in the 6.5.4 release, igore for now
+ ret = BCM_ERR_NOENT;
+ break;
+ */
+ }
+ }while(0);
+ return ret;
+}
+
+/**
+ * @brief The vsi_service_tag_add function add the service tag of a flow to a vsi target service.
+ *
+ * @param unit switch device id
+ * @param p_vsi_target a pointer to the vsi service
+ * @param p_flow a pointer to a flow that define the service tag need to be added
+ * @param p_svc_tag_indx a pointer to store the return service tag index that just added
+ *
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_vsi_service_tag_add(int unit, bal_sw_vsi_service *p_vsi_target, bcmbal_flow_cfg *p_flow, uint32_t *p_svc_tag_indx)
+{
+ bal_sw_lif_pkt_tag svc_pkt_tag = {0};
+ bal_sw_vsi_service *p_vsi_service;
+
+ /* input parameters checking */
+ if (p_flow == NULL || p_vsi_target == NULL || p_svc_tag_indx == NULL)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "invalid parameters when adding vsi service tag \n");
+ return BCM_ERR_PARM;
+ }
+
+ /* find out if the service tag already exist */
+ svc_pkt_tag.type = p_flow->data.classifier.pkt_tag_type;
+ svc_pkt_tag.o_vid = p_flow->data.classifier.o_vid;
+ svc_pkt_tag.i_vid = p_flow->data.classifier.i_vid;
+ p_vsi_service = bal_sw_util_dpp_vsi_service_get_by_tag(&svc_pkt_tag, p_svc_tag_indx);
+ if (p_vsi_service)
+ {
+ /* if the service tag already exist in the system, it has to be within the same vsi.
+ We don't allow same service tag to be serviced by more than one vsi
+ */
+ if(p_vsi_service != p_vsi_target)
+ {
+ return BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ return BCM_ERR_OK;
+ }
+ }
+
+ /* now add the tag to the list */
+ p_vsi_target->pkt_tag[p_vsi_target->num_tag] = svc_pkt_tag;
+ *p_svc_tag_indx = p_vsi_target->num_tag;
+ p_vsi_target->num_tag ++;
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The vsi_service_tag_rem function remove the service tag index by svc_tag_indx from a vsi service.
+ *
+ * @param unit switch device id
+ * @param p_vsi_svc a pointer to the vsi service
+ * @param svc_tag_indx a service tag index point to the service tag list that need to be removed
+ *
+ * @return error code
+ */
+bcmos_errno bal_sw_util_dpp_vsi_service_tag_rem(int unit, bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx)
+{
+ int i;
+ /* input parameters checking */
+ if (p_vsi_svc == NULL || p_vsi_svc->num_tag <= svc_tag_indx)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, "invalid parameters when removing vsi service tag \n");
+ return BCM_ERR_PARM;
+ }
+ /* compact the tag list */
+ for(i=svc_tag_indx; i<p_vsi_svc->num_tag-1; i++)
+ {
+ p_vsi_svc->pkt_tag[i] = p_vsi_svc->pkt_tag[i+1];
+ }
+ memset(&p_vsi_svc->pkt_tag[i], 0, sizeof (bal_sw_lif_pkt_tag));
+
+ (p_vsi_svc->num_tag)--;
+ return BCM_ERR_OK;
+}
+
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+/*@}*/
+
+
diff --git a/bal_release/src/core/util/switch/dpp/bal_dpp_vswitch.h b/bal_release/src/core/util/switch/dpp/bal_dpp_vswitch.h
new file mode 100644
index 0000000..43ddd93
--- /dev/null
+++ b/bal_release/src/core/util/switch/dpp/bal_dpp_vswitch.h
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+ /**
+ * @file bal_dpp_vswitch.h
+ * @brief BAL Switch util helper functions prototype
+ * @addtogroup sw_util
+ */
+#ifndef _BAL_DPP_VSWITCH_H_
+#define _BAL_DPP_VSWITCH_H_
+
+#include "bal_switch_flow.h"
+
+/* DPP multicast group offsets - use vsi as base */
+/* The mc group should not overlap, so the following setting limit system to 0x1000 vsi */
+#define BAL_DPP_US_FLOOD_OFFSET 0x0
+#define BAL_DPP_DS_FLOOD_OFFSET 0x1000
+#define BAL_DPP_MC_OFFSET 0x2000
+
+#define MAX_SVC_PER_VSI 8
+
+/*@{*/
+#ifndef TEST_SW_UTIL_LOOPBACK
+
+typedef struct bal_sw_lif_port bal_sw_lif_port;
+struct bal_sw_lif_port
+{
+ uint32_t port;
+ uint32_t gport;
+ int32_t use_count;
+};
+
+typedef struct bal_sw_lif_pkt_tag bal_sw_lif_pkt_tag;
+struct bal_sw_lif_pkt_tag
+{
+ uint32_t type;
+ uint32_t o_vid;
+ uint32_t i_vid;
+ uint32_t num_port;
+ bal_sw_lif_port port[MAX_NET_PORT];
+};
+
+typedef struct bal_sw_vsi_service bal_sw_vsi_service;
+struct bal_sw_vsi_service
+{
+ uint32_t num_tag;
+ bal_sw_lif_pkt_tag pkt_tag[MAX_SVC_PER_VSI];
+ uint32_t vswitch;
+ uint32_t us_flood_grp_id;
+ uint32_t ds_flood_grp_id;
+ int32_t use_count;
+ TAILQ_ENTRY(bal_sw_vsi_service) next_service;
+};
+
+extern bcmos_errno bal_sw_util_dpp_vsi_service_port_add(int unit, bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx, uint32_t port, int32_t *p_gport);
+extern bcmos_errno bal_sw_util_dpp_vsi_service_port_rem(int unit, bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx, uint32_t port);
+extern bcmos_errno bal_sw_util_dpp_vsi_service_tag_add(int unit, bal_sw_vsi_service *p_vsi_svc, bcmbal_flow_cfg *p_flow, uint32_t *p_svc_tag_indx);
+extern bcmos_errno bal_sw_util_dpp_vsi_service_tag_rem(int unit, bal_sw_vsi_service *p_vsi_svc, uint32_t svc_tag_indx);
+extern bal_sw_vsi_service *bal_sw_util_dpp_vsi_service_create(int unit, bcmbal_flow_cfg *p_flow, uint32_t *p_svc_tag_indx);
+extern bcmos_errno bal_sw_util_dpp_vsi_service_destroy(int unit, bal_sw_vsi_service *p_vsi_svc);
+extern bcmos_errno bal_sw_util_vsi_list_init(void);
+
+#endif /* TEST_SW_UTIL_LOOPBACK */
+/*@}*/
+#endif
diff --git a/bal_release/src/core/util/switch/esw/Makefile b/bal_release/src/core/util/switch/esw/Makefile
new file mode 100644
index 0000000..88473f7
--- /dev/null
+++ b/bal_release/src/core/util/switch/esw/Makefile
@@ -0,0 +1,43 @@
+###############################################################################
+#
+# <: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.
+#
+# :>
+#
+###############################################################################
+# BAL Switch Util ESW
+MOD_NAME = switch_util_esw
+MOD_TYPE = lib
+MOD_DEPS = dev_log utils bal_api bal_app_utils
+srcs = bal_esw_acc_term.c bal_esw_flow.c
+EXTRA_CFLAGS += -I$(SRC_DIR)/../../../main -I$(SRC_DIR)/..
+
+ifeq ("$(TEST_SW_UTIL_LOOPBACK)", "y")
+ MOD_DEFS += -DTEST_SW_UTIL_LOOPBACK
+else
+ MOD_DEPS += switch_sdk
+endif
+
diff --git a/bal_release/src/core/util/switch/esw/bal_esw_acc_term.c b/bal_release/src/core/util/switch/esw/bal_esw_acc_term.c
new file mode 100755
index 0000000..ef9ded3
--- /dev/null
+++ b/bal_release/src/core/util/switch/esw/bal_esw_acc_term.c
@@ -0,0 +1,132 @@
+/******************************************************************************
+ *
+ * <: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 TEST_SW_UTIL_LOOPBACK
+
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_util.h"
+#include "bal_switch_acc_term.h"
+#include "bal_esw_acc_term.h"
+
+#include <bcm/types.h>
+#include <bcm/port.h>
+
+/**
+ * @file bal_esw_acc_term.c
+ * @brief BAL Switch util functions that handle access terminal requests on Enterprise SWitch
+ * @addtogroup sw_util
+ *
+ */
+
+/*@{*/
+
+
+/**
+ * @brief Connect access terminal with ESW as part of the components
+ *
+ * This routine is called by sw_util_access_terminal_connect in the BAL core
+ * to execute ESW specific API for access_terminal_connect request
+ *
+ * @param p_net_map Pointer to the net ports mapping from logical numbrer to physical number
+ * @param p_pon_map Pointer to the pon ports mapping from logical numbrer to physical number
+ * @return bcmos_errno
+ */
+bcmos_errno sw_util_esw_acc_term_connect(bal_swapp_port *p_net_map, bal_swapp_port *p_pon_map )
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ int rc = 0;
+ bal_swapp_port *port;
+ bcm_pbmp_t pon_pbmp, net_pbmp;
+
+ BCM_LOG(INFO, log_id_sw_util, " KT2 - Got a access terminal CONNECT\n");
+
+ BCM_PBMP_CLEAR(pon_pbmp);
+ BCM_PBMP_CLEAR(net_pbmp);
+
+ /* setup the device ID - This is very hardware specific */
+ port = p_net_map;
+ /* -1 indicate the end of table */
+ while(port->pbm_id != -1)
+ {
+ /* add port to the net list */
+ BCM_PBMP_PORT_ADD(net_pbmp, port->pbm_id);
+ port++;
+ }
+
+ port = p_pon_map;
+ while(port->pbm_id != -1)
+ {
+ /* add port to the pon list */
+ BCM_PBMP_PORT_ADD(pon_pbmp, port->pbm_id);
+ port++;
+ }
+
+ /* set up the valid egress ports for pon facing ports */
+ port = p_pon_map;
+ while(port->pbm_id != -1)
+ {
+ rc = bcm_port_egress_set(port->device_id, port->pbm_id, 0, /* modid */ net_pbmp);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util, " ESW - Add port %d to pon interface failed\n", port->pbm_id );
+ }
+ port++;
+ }
+
+ /* set up the valid egress ports for net facing ports */
+ port = p_net_map;
+ while(port->pbm_id != -1)
+ {
+ rc = bcm_port_egress_set(port->device_id, port->pbm_id, 0, /* modid */ pon_pbmp);
+ if (rc)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ESW - Add port %d to net interface failed\n", port->pbm_id );
+ }
+ port++;
+ }
+
+ /* translate ING error code to BAL error code */
+ if (rc)
+ {
+ ret = BCM_ERR_INTERNAL;
+ }
+ else
+ {
+ ret = BCM_ERR_OK;
+ }
+ return ret;
+}
+
+/*@}*/
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
diff --git a/bal_release/src/core/util/switch/esw/bal_esw_acc_term.h b/bal_release/src/core/util/switch/esw/bal_esw_acc_term.h
new file mode 100755
index 0000000..1343f68
--- /dev/null
+++ b/bal_release/src/core/util/switch/esw/bal_esw_acc_term.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_esw_acc_term.h
+ *
+ * @brief bal switch esw util access terminal service function header file
+ *
+ * @addtogroup sw_util
+ */
+
+#ifndef _BAL_ESW_ACC_TERM_H_
+#define _BAL_ESW_ACC_TERM_H_
+
+/*@{*/
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+#include "bal_switch_acc_term.h"
+
+extern bcmos_errno sw_util_esw_acc_term_connect(bal_swapp_port *p_net_map, bal_swapp_port *p_pon_map);
+
+/*@}*/
+
+#endif
diff --git a/bal_release/src/core/util/switch/esw/bal_esw_flow.c b/bal_release/src/core/util/switch/esw/bal_esw_flow.c
new file mode 100755
index 0000000..27d33af
--- /dev/null
+++ b/bal_release/src/core/util/switch/esw/bal_esw_flow.c
@@ -0,0 +1,555 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_esw_flow.c
+ * @brief BAL Switch util functions that handle flow requests
+ * @addtogroup sw_util
+ */
+
+ /*@{*/
+#include <bal_common.h>
+#include <bcm_dev_log.h>
+#include <bal_msg.h>
+#include "bal_switch_flow.h"
+#include "flow_fsm.h"
+#include "bcmos_errno.h"
+#include "bal_switch_util.h"
+
+#ifndef TEST_SW_UTIL_LOOPBACK
+#include <bcm/types.h>
+#include <sal/core/libc.h>
+#ifndef sal_memset
+#define sal_memset memset
+#endif
+#include <bcm/port.h>
+#include <bcm/vlan.h>
+#include <bcm/field.h>
+#include <bcm/error.h>
+#include <sal/core/libc.h>
+
+#include "bal_switch_acc_term.h"
+#include "bal_esw_flow.h"
+/**
+ * @brief The acl add function add an Access Control Rule in the switch VCAP/ICAP/ECAP
+ * to perform action based on flow classifier
+ *
+ * @param unit the switch unit this rule is to be added
+ * @param p_flow a pointer to the flow definition the created rule will be based on
+ * @return error code
+ */
+static bcm_field_group_t esw_group_id = 0;
+/* add an ingress ACL rule */
+static bcmos_errno bal_swapp_esw_acl_add(int unit, bcmbal_flow_cfg *p_flow)
+{
+ uint32_t ret, j;
+ uint32_t nni_phy;
+ int vid;
+ bcm_field_qset_t qset;
+ bcm_field_entry_t eid;
+ bcm_mac_t bcast_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+ bcm_mac_t dst_mask = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+
+ do
+ {
+ vid = p_flow->data.classifier.o_vid;
+
+ /* VCAP - bcmFieldQualifyStageLookup, ICAP - bcmFieldQualifyStageIngress, ECAP - bcmFieldQualifyStageEgress */
+ /* The KT2 resources allow only limit number of qset - indexed by esw_group_id, create qset when necessary */
+ if (0 == esw_group_id)
+ {
+ BCM_FIELD_QSET_INIT(qset);
+ BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyStageLookup);
+ BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyOuterVlan);
+ BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort);
+ BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyDstMac);
+ ret = bcm_field_group_create(unit, qset, BCM_FIELD_GROUP_PRIO_ANY, &esw_group_id);
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to create field - %d\n", ret );
+ break;
+ }
+ }
+
+ /* if action is to drop broadcast, add an ACL in nni VCAP to drop it */
+ if ( p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_DISCARD_DS_BCAST)
+ {
+ /* loop through all nni ports */
+ for(j=0; -1 != (nni_phy = bal_bcm_net_inf_pbm_get(j)); j++)
+ {
+ if ( bal_bcm_net_inf_dev_get(j) != unit)
+ {
+ continue;
+ }
+
+ ret = bcm_field_entry_create(unit, esw_group_id, &eid);
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to create field entry for port %d - ret = %d\n", nni_phy, ret );
+ break;
+ }
+
+ ret = bcm_field_qualify_DstMac(unit, eid, bcast_mac, dst_mask);
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to set field dst mac qualifier %d - ret = %d\n", nni_phy, ret );
+ break;
+ }
+
+ ret = bcm_field_qualify_OuterVlanId(unit, eid, vid, 0xffff);
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to set field outer vlan qualifier %d - ret = %d\n", nni_phy, ret );
+ break;
+ }
+ ret = bcm_field_action_add(unit, eid, bcmFieldActionDrop, 0, 0);
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to add action to the field entry %d - ret = %d\n", nni_phy, ret );
+ break;
+ }
+
+ ret = bcm_field_entry_install(unit, eid);
+ if (ret != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to install field entry %d - ret = %d\n", nni_phy, ret );
+ break;
+ }
+ } /* for loop */
+ } /* if drop bcast */
+ } while(0);
+
+
+ if (ret != BCM_E_NONE)
+ {
+ return BCM_ERR_INTERNAL;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/**
+ * @brief The ingress vlan translation function program switch to
+ * translate packet vlan attributes before the switch vaidate the
+ * vlan membership of the packets
+ * @param unit the switch unit this translation is perfromed
+ * @param p_flow a pointer to the flow that contains translation action
+ * @return error code
+ */
+static bcmos_errno bal_swapp_esw_ivlanx(int unit, bcmbal_flow_cfg *p_flow)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcm_gport_t pon_gport;
+ uint32_t pon_phy_pbm;
+ int bcm_rc;
+
+ /* find out which PON this action is to be performed */
+ /* map pon logical port to physical port */
+ pon_phy_pbm = bal_bcm_pon_inf_pbm_get(p_flow->data.access_int_id);
+ /* create local gport based on pon physical port number */
+ BCM_GPORT_LOCAL_SET(pon_gport, pon_phy_pbm);
+
+ do
+ {
+ /* For TR-156 1:1 uptream single tagged packets,
+ S-tag add acton is performed in the INGRESS vlan translator.
+ */
+ if (BCMBAL_FLOW_TYPE_UPSTREAM == p_flow->key.flow_type)
+ {
+ if ( p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG )
+ {
+ uint32_t u_ovid, u_ivid;
+ bcm_vlan_action_set_t u_action;
+ bcm_vlan_action_set_t_init(&u_action);
+
+ /* set gpon ingress translaton to add outer tag on upstream packets */
+ u_action.new_outer_vlan = p_flow->data.action.o_vid;
+ u_action.priority = p_flow->data.action.o_pbits;
+
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_SINGLE_TAG:
+ u_action.ot_outer = bcmVlanActionAdd;
+ u_action.ot_outer_pkt_prio = bcmVlanActionReplace;
+ u_ovid = p_flow->data.classifier.o_vid;
+ u_ivid = BCM_VLAN_NONE;
+ break;
+ default: /* not supported, goto while(0) */
+ u_ovid = BCM_VLAN_NONE;
+ u_ivid = BCM_VLAN_NONE;
+ ret = BCM_ERR_INTERNAL;
+ continue;
+ }
+ /* enable ingress vlan translation on specified port */
+ bcm_rc = bcm_vlan_control_port_set(unit, pon_gport, bcmVlanTranslateIngressEnable, 1);
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to enable ingress vlan translation on port %d - %d\n",
+ pon_phy_pbm, bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* set the outer vlan id as lookup key - i.e. packet filtering key */
+ bcm_rc = bcm_vlan_control_port_set(unit, pon_gport, bcmVlanPortTranslateKeyFirst, bcmVlanTranslateKeyOuter);
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to set upstream lookup key on port %d - %d\n",
+ pon_phy_pbm, bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* install the action into ingress vlan translation table */
+ bcm_rc = bcm_vlan_translate_action_add(unit, pon_gport, bcmVlanTranslateKeyOuter, u_ovid, u_ivid, &u_action);
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to set ingress action on port %d - %d\n",
+ pon_phy_pbm, bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow upstream action 0x%x not supported\n", p_flow->data.action.cmds_bitmask);
+
+ ret = BCM_ERR_NOT_SUPPORTED;
+ }
+ }
+
+ } while(0);
+
+ return ret;
+}
+
+/**
+ * @brief The engress vlan translation function program switch to
+ * translate packet vlan attributes before the packets were sent out
+ *
+ * @param unit the switch unit this translation is perfromed
+ * @param p_flow a pointer to the flow that contains translation action
+ * @return error code
+ */
+static bcmos_errno bal_swapp_esw_evlanx(int unit, bcmbal_flow_cfg *p_flow)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcm_gport_t pon_gport;
+ uint32_t pon_phy_pbm;
+ int bcm_rc;
+
+ /* find out which PON this action is to be performed */
+ /* map pon logical port to physical port */
+ pon_phy_pbm = bal_bcm_pon_inf_pbm_get(p_flow->data.access_int_id);
+ /* create local gport based on pon physical port number */
+ BCM_GPORT_LOCAL_SET(pon_gport, pon_phy_pbm);
+
+ do
+ {
+ /* For TR-156 1:1 downstream double tagged packets,
+ S-tag remove acton is performed in the EGRESS vlan translator.
+ */
+ if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow->key.flow_type)
+ {
+
+ if ( p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG )
+ {
+ /* set gpon egress translaton to drop outer tag of double tag downstream packets */
+ uint32_t d_ovid, d_ivid;
+ bcm_vlan_action_set_t d_action;
+ bcm_vlan_action_set_t_init(&d_action);
+ switch(p_flow->data.classifier.pkt_tag_type)
+ {
+ case BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG:
+ d_action.dt_outer = bcmVlanActionDelete;
+ d_ovid = p_flow->data.classifier.o_vid;
+ d_ivid = p_flow->data.classifier.i_vid;
+ break;
+
+ default: /* not supported, goto while(0) */
+ d_ovid = BCM_VLAN_NONE;
+ d_ivid = BCM_VLAN_NONE;
+ ret = BCM_ERR_INTERNAL;
+ continue;
+ }
+ /* enable egress vlan translation on specified port */
+ bcm_rc = bcm_vlan_control_port_set(unit, pon_gport, bcmVlanTranslateEgressEnable, 1);
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to enable egress vlan translation on port %d - %d\n",
+ pon_phy_pbm, bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+
+ /* install the action into egress vlan translation table */
+ bcm_rc = bcm_vlan_translate_egress_action_add(unit, pon_gport, d_ovid, d_ivid, &d_action);
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to set egress action on port %d - %d\n",
+ pon_phy_pbm, bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ }
+ else
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow downstream action 0x%x not supported\n", p_flow->data.action.cmds_bitmask);
+
+ ret = BCM_ERR_NOT_SUPPORTED;
+ }
+
+ }
+
+ } while(0);
+
+ return ret;
+}
+
+
+/**
+ * @brief The flow add function program KT2 to forward packets that have
+ * specified attributes to the designated ports.
+ * The packets is modified before egress
+ * On the downstream, an access id (outer vlan tag) is added to the packets
+ * On the upstream, outer vlan tag (access id) is removed from the packets
+ *
+ * @param iwf_mode The InterWorking Function mode - DIRECT or PER-FLOW
+ * @param p_flow A pointer to the requested add flow info
+ * @return error code
+ */
+bcmos_errno bal_sw_util_esw_flow_add(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcm_gport_t pon_gport;
+ uint32_t pon_phy_pbm;
+ bcm_vlan_t vlan_id;
+ bcm_gport_t nni_gport;
+ uint32_t nni_phy_pbm;
+ int ii;
+ int bcm_rc;
+ int unit = bal_bcm_pon_inf_dev_get(p_flow->data.access_int_id);
+
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got an ESW flow request - iwf_mode=%d flow_id=%d sub_port=%d svc_id=%d\n",
+ iwf_mode,
+ p_flow->key.flow_id, p_flow->data.access_int_id, p_flow->data.svc_port_id);
+ BCM_LOG(DEBUG, log_id_sw_util,
+ " classifier - mask=0x%llx otpid=%x itpid=%x ovid=%x ivid=%x\n",
+ (unsigned long long)p_flow->data.classifier.presence_mask,
+ p_flow->data.classifier.o_tpid, p_flow->data.classifier.i_tpid,
+ p_flow->data.classifier.o_vid, p_flow->data.classifier.i_vid);
+
+ /*
+ * First, validate that the specified PON has at least one NNI port on the same device.
+ * If not, return an error, as this is not supported.
+ */
+ ii = 0;
+ ret = BCM_ERR_NOT_SUPPORTED;
+ /* walk through the entire mapping table */
+ while(-1 != bal_bcm_net_inf_pbm_get(ii))
+ {
+ if(bal_bcm_net_inf_dev_get(ii) == unit)
+ {
+ ret = BCM_ERR_OK;
+ break;
+ }
+ ii++; /* Next NNI */
+ }
+
+ do
+ {
+ /*
+ * Check return code from device check above. Return if there was an error.
+ */
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " ERROR: no network port is on the same device as access port %d\n", p_flow->data.access_int_id);
+ break;
+ }
+
+ /* create vlan domain for this flow */
+ vlan_id = (bcm_vlan_t)p_flow->data.classifier.o_vid;
+ bcm_rc = bcm_vlan_create(unit, vlan_id);
+
+ /* if OK or already existed, continue */
+ if (bcm_rc != BCM_E_NONE && bcm_rc != BCM_E_EXISTS)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " failed to create vlan %d on unit %d - bcm_rc:%d\n", vlan_id, unit, bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ else
+ {
+ BCM_LOG(INFO, log_id_sw_util,
+ " vlan %d %s on unit %d - bcm_rc:%d\n",
+ vlan_id,
+ (BCM_E_EXISTS == bcm_rc) ? "reused" : "created",
+ unit,
+ bcm_rc );
+ }
+
+ /* map pon logical port to physical port */
+ pon_phy_pbm = bal_bcm_pon_inf_pbm_get(p_flow->data.access_int_id);
+
+ /* create gport based on pon physical port number */
+ BCM_GPORT_LOCAL_SET(pon_gport, pon_phy_pbm);
+
+ /* add the specified pon to vlan */
+ bcm_rc = bcm_vlan_gport_add(unit, vlan_id, pon_gport, BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP);
+
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to add pon %d (pbm %d, gport %d) into vlan %d - %d\n",
+ p_flow->data.access_int_id, pon_phy_pbm, pon_gport, vlan_id, bcm_rc );
+
+ ret = BCM_ERR_INTERNAL;
+
+ break;
+ }
+
+ /* Add all the NNI ports that are on the same device to the vlan as well */
+
+ ii = 0; /* Start with the first NNI logical interface */
+
+ /* map nni logical ports to physical ports */
+ while(-1 != (nni_phy_pbm = bal_bcm_net_inf_pbm_get(ii)))
+ {
+ if ( bal_bcm_net_inf_dev_get(ii) != unit)
+ {
+ continue;
+ }
+ /* create gport based on nni physical port number */
+ BCM_GPORT_LOCAL_SET(nni_gport, nni_phy_pbm);
+
+ bcm_rc = bcm_vlan_gport_add(unit, vlan_id, nni_gport, BCM_VLAN_GPORT_ADD_VP_VLAN_MEMBERSHIP);
+
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to add nni %d (pbm %d, gport %d) into vlan %d - %d\n",
+ ii, nni_phy_pbm, nni_gport, vlan_id, bcm_rc );
+
+ ret = BCM_ERR_INTERNAL;
+
+ break;
+ }
+
+ ii++; /* Next NNI */
+ }
+
+ /* perform the ACTION */
+ if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(p_flow, flow, action)
+ /* && BCMOS_TRUE == BCMBAL_ATTRIBUTE_CFG_PROP_IS_SET(&p_flow->data.action, action, action_cmds_bitmask) */
+ )
+ {
+ BCM_LOG(INFO, log_id_sw_util,
+ " Got a flow action - flow type = %d, cmd=%d in_ovid=%d, out_ovid=%d\n",
+ p_flow->key.flow_type, p_flow->data.action.cmds_bitmask,
+ p_flow->data.classifier.i_vid, p_flow->data.classifier.o_vid);
+
+ /* enable vlan translation */
+ bcm_rc = bcm_vlan_control_set(unit, bcmVlanTranslate, 1);
+ if (bcm_rc != BCM_E_NONE)
+ {
+ BCM_LOG(ERROR, log_id_sw_util,
+ " flow fail to enable vlan translation - %d\n",
+ bcm_rc );
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ /* For TR-156 1:1 downstream,
+ ACTIONs are performed on the EGRESS vlan translator.
+ For TR-156 1:1 upstream,
+ ACTIONs are perform on the INGRESS vlan translator.
+ For TR-156 N:1 there is no actions for switch
+ The outer tag adding is per PON base, i.e. upstream packets with same
+ inner vid can add different outer vid based on receiving PON
+ */
+ if (BCMBAL_FLOW_TYPE_UPSTREAM == p_flow->key.flow_type)
+ {
+ if ( p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG )
+ {
+ ret = bal_swapp_esw_ivlanx(unit, p_flow);
+ }
+ }
+ else if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow->key.flow_type)/* downstream */
+ {
+ if ( p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG )
+ {
+ ret = bal_swapp_esw_evlanx(unit, p_flow);
+ }
+ }
+ else /* broadcast */
+ {
+ if ( p_flow->data.action.cmds_bitmask & BCMBAL_ACTION_CMD_ID_DISCARD_DS_BCAST)
+ {
+ ret = bal_swapp_esw_acl_add(unit, p_flow);
+ }
+
+ }
+ } /* end if ACTION set */
+
+ } while(0);
+
+
+ return ret;
+}
+
+/**
+ * @brief The flow remove function remove switch resource that were allocated during ADD
+ *
+ * @param iwf_mode The InterWorking Function mode - DIRECT or PER-FLOW
+ * @param p_flow A pointer to the requested add flow info
+ * @return error code
+ */
+bcmos_errno bal_sw_util_esw_flow_remove(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow)
+{
+ return BCM_ERR_OK;
+}
+
+#endif /* #ifndef TEST_SW_UTIL_LOOPBACK */
+
+/*@}*/
diff --git a/bal_release/src/core/util/switch/esw/bal_esw_flow.h b/bal_release/src/core/util/switch/esw/bal_esw_flow.h
new file mode 100755
index 0000000..3146222
--- /dev/null
+++ b/bal_release/src/core/util/switch/esw/bal_esw_flow.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_esw_flow.h
+ *
+ * @brief Function Prototype for switch app flow functions for ESW
+ *
+ * @ingroup switch_app
+ */
+
+#ifndef _BAL_ESW_FLOW_H_
+#define _BAL_ESW_FLOW_H_
+
+#include "bal_switch_util.h"
+
+/*@{*/
+
+bcmos_errno bal_sw_util_esw_flow_add(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow);
+bcmos_errno bal_sw_util_esw_flow_remove(bcmbal_iwf_mode iwf_mode, bcmbal_flow_cfg *p_flow);
+
+/*@}*/
+
+#endif
diff --git a/bal_release/src/datamodel/bal.objset b/bal_release/src/datamodel/bal.objset
new file mode 100644
index 0000000..e8801cf
--- /dev/null
+++ b/bal_release/src/datamodel/bal.objset
@@ -0,0 +1,3901 @@
+<?xml version="1.0" encoding="utf-8"?>
+<ElementSet Version="2.1">
+ <KeyValuePairs>
+ <KeyValuePair>
+ <Key>SupportsAutoCfg</Key>
+ <Value>False</Value>
+ </KeyValuePair>
+ </KeyValuePairs>
+ <Label>
+ <ShortName>bal</ShortName>
+ <LongName>BAL</LongName>
+ <Description>BAL Object Model</Description>
+ </Label>
+ <CustomTypes>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>access_id</ShortName>
+ <LongName>Access ID</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>action</ShortName>
+ <LongName>action</LongName>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>cmds_bitmask</ShortName>
+ <LongName>Commands bitmask</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>action_cmd_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>o_vid</ShortName>
+ <LongName>Outer vid</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>o_pbits</ShortName>
+ <LongName>Outer pbits</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>o_tpid</ShortName>
+ <LongName>Outer tpid</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>i_vid</ShortName>
+ <LongName>Inner vid</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>i_pbits</ShortName>
+ <LongName>Inner pbits</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>i_tpid</ShortName>
+ <LongName>Inner tpid</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>action_cmd_id</ShortName>
+ <LongName>action_cmd_id</LongName>
+ </Label>
+ <Flags>True</Flags>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>add_outer_tag</ShortName>
+ <LongName>Add outer tag</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>remove_outer_tag</ShortName>
+ <LongName>Remove outer tag</LongName>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>xlate_outer_tag</ShortName>
+ <LongName>Translate outer tag</LongName>
+ </Label>
+ <Value>4</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>xlate_two_tags</ShortName>
+ <LongName>Translate two tags</LongName>
+ </Label>
+ <Value>8</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>discard_ds_bcast</ShortName>
+ <LongName>Discard downstream broadcast</LongName>
+ <Description>Used to satisfy TR-156 Issue 3 R-111</Description>
+ </Label>
+ <Value>16</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>discard_ds_unknown</ShortName>
+ <LongName>Discard downstream unknown</LongName>
+ <Description>Used to satisfy TR-156 Issue 3 R-109</Description>
+ </Label>
+ <Value>32</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>add_two_tags</ShortName>
+ <LongName>Add two tags</LongName>
+ </Label>
+ <Value>64</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>remove_two_tags</ShortName>
+ <LongName>Remove two tags</LongName>
+ </Label>
+ <Value>128</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>remark_pbits</ShortName>
+ <LongName>Remark pbits</LongName>
+ <Description>Set the outer tag pbits</Description>
+ </Label>
+ <Value>256</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>copy_pbits</ShortName>
+ <LongName>Copy pbits</LongName>
+ <Description>Copy the inner pbits to outer pbits</Description>
+ </Label>
+ <Value>512</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>reverse_copy_pbits</ShortName>
+ <LongName>Reverse copy pbits</LongName>
+ <Description>Copy the outer pbits to inner pbits</Description>
+ </Label>
+ <Value>1024</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>dscp_to_pbits</ShortName>
+ <LongName>Dscp to pbits</LongName>
+ <Description>Copy the L4 DSCP to outer pbits</Description>
+ </Label>
+ <Value>2048</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>trap_to_host</ShortName>
+ <LongName>Trap to host</LongName>
+ <Description>Not a valid action for a group object member</Description>
+ </Label>
+ <Value>4096</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>aggregation_port_id</ShortName>
+ <LongName>Aggregation port id</LongName>
+ </Label>
+ <BaseType>
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>classifier</ShortName>
+ <LongName>classifier</LongName>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>o_tpid</ShortName>
+ <LongName>Outer tpid</LongName>
+ <Description>Outer TPID of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>o_vid</ShortName>
+ <LongName>Outer vid</LongName>
+ <Description>Outer VID of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>i_tpid</ShortName>
+ <LongName>Inner tpid</LongName>
+ <Description>Inner TPID of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>i_vid</ShortName>
+ <LongName>Inner vid</LongName>
+ <Description>Inner VID of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>o_pbits</ShortName>
+ <LongName>Outer Pbits</LongName>
+ <Description>Outer PBITS of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>i_pbits</ShortName>
+ <LongName>Inner Pbits</LongName>
+ <Description>Inner PBITS of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ether_type</ShortName>
+ <LongName>Ether type</LongName>
+ <Description>Ethertype of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>dst_mac</ShortName>
+ <LongName>Destination mac</LongName>
+ <Description>Destination MAC address of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeWellKnown">
+ <WellKnownType>MacAddress</WellKnownType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>src_mac</ShortName>
+ <LongName>Source mac</LongName>
+ <Description>Source MAC address of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeWellKnown">
+ <WellKnownType>MacAddress</WellKnownType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ip_proto</ShortName>
+ <LongName>IP Protocol</LongName>
+ <Description>IP protocol of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>dst_ip</ShortName>
+ <LongName>Destination IP address</LongName>
+ <Description>Destination IP address of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeWellKnown">
+ <WellKnownType>IPv4Address</WellKnownType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>src_ip</ShortName>
+ <LongName>Source IP address</LongName>
+ <Description>Source IP address of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeWellKnown">
+ <WellKnownType>IPv4Address</WellKnownType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>src_port</ShortName>
+ <LongName>Source port</LongName>
+ <Description>Source port of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>dst_port</ShortName>
+ <LongName>Destination port</LongName>
+ <Description>Destination port of the packet to be classified</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>pkt_tag_type</ShortName>
+ <LongName>Packet tag type</LongName>
+ <Description>The tag type of the ingress packets</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>pkt_tag_type</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>control</ShortName>
+ <LongName>control</LongName>
+ <Description>Generic enable/disable enumeration</Description>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>disable</ShortName>
+ <LongName>disable</LongName>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>enable</ShortName>
+ <LongName>enable</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>cookie</ShortName>
+ <LongName>cookie</LongName>
+ </Label>
+ <BaseType>
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeClassifiedStructure">
+ <Label>
+ <ShortName>dest</ShortName>
+ <LongName>Packet destination</LongName>
+ </Label>
+ <Options>ValueType</Options>
+ <CommonFields>
+ <Field>
+ <Label>
+ <ShortName>type</ShortName>
+ <LongName>packet destination</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>dest_type</ShortName>
+ </FieldType>
+ </Field>
+ </CommonFields>
+ <ClassifierFieldName>type</ClassifierFieldName>
+ <ClassifiedStructures>
+ <ClassifiedStructure>
+ <ClassifierValue>nni</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Options>ValueType</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>int_id</ShortName>
+ <LongName>Interface ID</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>sub_term</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Options>ValueType</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>Subscriber terminal ID</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_uni</ShortName>
+ <LongName>Subscriber terminal UNI</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>int_id</ShortName>
+ <LongName>Interface ID</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>host</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Options>ValueType</Options>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ </ClassifiedStructures>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>dest_type</ShortName>
+ <LongName>Destination type</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>nni</ShortName>
+ <LongName>nni</LongName>
+ <Description>for packets being sent to the NNI</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>sub_term</ShortName>
+ <LongName>subscriber terminal</LongName>
+ <Description>for packets being sent to a subscriber terminal</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>host</ShortName>
+ <LongName>host</LongName>
+ <Description> for packet indications received from NNI or SUB_TERM and being sent to the host</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>ds_miss_mode</ShortName>
+ <LongName>Downstrean action for unknown packets</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>discard</ShortName>
+ <LongName>Discard</LongName>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>broadcast</ShortName>
+ <LongName>Broadcast</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>vid</ShortName>
+ <LongName>Vid</LongName>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>extra_bw_eligibility_type</ShortName>
+ <LongName>extra_bw_eligibility_type</LongName>
+ <Description>Extra BW Eligibility Type</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>none</ShortName>
+ <LongName>none</LongName>
+ <Description>None</Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>not_assured</ShortName>
+ <LongName>not_assured</LongName>
+ <Description>Not assured</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>best_effort</ShortName>
+ <LongName>best_effort</LongName>
+ <Description>Best effort</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>flow_id</ShortName>
+ <LongName>flow id</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>flow_type</ShortName>
+ <LongName>Flow Type</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>upstream</ShortName>
+ <LongName>Upstream flow</LongName>
+ <Description>Upstream flow</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>downstream</ShortName>
+ <LongName>Downstream flow</LongName>
+ <Description>Downstream Flow</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>broadcast</ShortName>
+ <LongName>Broadcast flow</LongName>
+ <Description>Broadcast Flow</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>multicast</ShortName>
+ <LongName>Multicast flow</LongName>
+ <Description>Multicast Flow</Description>
+ </Label>
+ <Value>4</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>group_id</ShortName>
+ <LongName>group id</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>group_member_cmd</ShortName>
+ <LongName>Member operation type</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>add_members</ShortName>
+ <LongName>Add new members</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>rem_members</ShortName>
+ <LongName>Remove existing members</LongName>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>set_members</ShortName>
+ <LongName>Replace members with new set</LongName>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>group_member_info</ShortName>
+ <LongName>Group Member Info</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>Access Interface ID</LongName>
+ <Description>Access interface id for this member</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port_id</ShortName>
+ <LongName>Service Port ID</LongName>
+ <Description>The multicast "GEM" for this member</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>action</ShortName>
+ <LongName>VLAN Actions</LongName>
+ <Description>VLAN actions</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>action</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>queue</ShortName>
+ <LongName>Egress queue</LongName>
+ <Description>Egress queue</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_queue_ref</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>group_owner</ShortName>
+ <LongName>group_owner</LongName>
+ <Description>owner of the group</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>none</ShortName>
+ <LongName>group_owner_none</LongName>
+ <Description>no owner</Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>multicast</ShortName>
+ <LongName>group_owner_multicast</LongName>
+ <Description>used as multicast group</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>unicast</ShortName>
+ <LongName>group_owner_unicast</LongName>
+ <Description>used as unicast group</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>Interface ID</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>intf_type</ShortName>
+ <LongName>Interface type</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>nni</ShortName>
+ <LongName>NNI Interface</LongName>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>pon</ShortName>
+ <LongName>POIN Interface</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>iwf_mode</ShortName>
+ <LongName>Interworking Function Mode</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>direct_mapping</ShortName>
+ <LongName>Direct mapping</LongName>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>per_flow</ShortName>
+ <LongName>Per flow </LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>password</ShortName>
+ <LongName>Password</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>arr</ShortName>
+ <LongName>Array</LongName>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </ElementType>
+ <MinimumLength>10</MinimumLength>
+ <MaximumLength>10</MaximumLength>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>percent</ShortName>
+ <LongName>percent</LongName>
+ <Description>Percent</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <MinimumValue>0</MinimumValue>
+ <MaximumValue>100</MaximumValue>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>pkt_tag_type</ShortName>
+ <LongName>Packet tag type</LongName>
+ </Label>
+ <Flags>True</Flags>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>untagged</ShortName>
+ <LongName>Untagged</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>single_tag</ShortName>
+ <LongName>Single tag</LongName>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>double_tag</ShortName>
+ <LongName>Double tag</LongName>
+ </Label>
+ <Value>4</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>registration_id</ShortName>
+ <LongName>Registration id</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>arr</ShortName>
+ <LongName>Array</LongName>
+ <Description>ONU registration ID</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </ElementType>
+ <MinimumLength>36</MinimumLength>
+ <MaximumLength>36</MaximumLength>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>serial_number</ShortName>
+ <LongName>Serial number</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>vendor_id</ShortName>
+ <LongName>vendor id</LongName>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </ElementType>
+ <MinimumLength>4</MinimumLength>
+ <MaximumLength>4</MaximumLength>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>vendor_specific</ShortName>
+ <LongName>vendor specific</LongName>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </ElementType>
+ <MinimumLength>4</MinimumLength>
+ <MaximumLength>4</MaximumLength>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>service_port_id</ShortName>
+ <LongName>Service port id</LongName>
+ </Label>
+ <BaseType>
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>sla</ShortName>
+ <LongName>SLA</LongName>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>min_rate</ShortName>
+ <LongName>Minimum rate</LongName>
+ <Description>The minimal rate for this flow, in kilobits per second (optional)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>max_rate</ShortName>
+ <LongName>Maximum rate</LongName>
+ <Description>The maximum rate for this flow, in kilobits per second (optional)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>state</ShortName>
+ <LongName>state</LongName>
+ <Description>Admin state values for access terminal object</Description>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>up</ShortName>
+ <LongName>Up</LongName>
+ <Description>Admin state up</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>down</ShortName>
+ <LongName>Down</LongName>
+ <Description>Admin state down</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>testing</ShortName>
+ <LongName>Testing</LongName>
+ <Description>Admin state testing</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>status</ShortName>
+ <LongName>status</LongName>
+ <Description>Oper status values</Description>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>up</ShortName>
+ <LongName>Up</LongName>
+ <Description>Oper status up</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>down</ShortName>
+ <LongName>Down</LongName>
+ <Description>Oper status down</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>testing</ShortName>
+ <LongName>Testing</LongName>
+ <Description>Oper status testing</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>not_present</ShortName>
+ <LongName>Not present</LongName>
+ <Description>Oper status not present</Description>
+ </Label>
+ <Value>4</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>lower_layer_down</ShortName>
+ <LongName>Lower layer down</LongName>
+ <Description>Oper status lower layer down</Description>
+ </Label>
+ <Value>5</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>unknown</ShortName>
+ <LongName>Unknown</LongName>
+ <Description>Oper status unknown</Description>
+ </Label>
+ <Value>6</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>sub_id</ShortName>
+ <LongName>Subterminal Terminal ID</LongName>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Constants>
+ <AliasConstantEntry>
+ <Label>
+ <ShortName>unknown</ShortName>
+ <LongName>Unknown</LongName>
+ </Label>
+ <Value>0xFFFF</Value>
+ </AliasConstantEntry>
+ </Constants>
+ </CustomType>
+ <CustomType Type="CustomTypeClassifiedStructure">
+ <Label>
+ <ShortName>tm_bac</ShortName>
+ <LongName>tm_bac</LongName>
+ <Description>Queue Buffer Admission Control</Description>
+ </Label>
+ <CommonFields>
+ <Field>
+ <Label>
+ <ShortName>type</ShortName>
+ <LongName>type</LongName>
+ <Description>Buffer Admission Control Type</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_bac_type</ShortName>
+ </FieldType>
+ </Field>
+ </CommonFields>
+ <ClassifierFieldName>type</ClassifierFieldName>
+ <ClassifiedStructures>
+ <ClassifiedStructure>
+ <ClassifierValue>taildrop</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>max_size</ShortName>
+ <LongName>max_size</LongName>
+ <Description>max number of packets in the queue</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>red</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>red</ShortName>
+ <LongName>red</LongName>
+ <Description>Random Early Discard configuration</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_red</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>wred</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>green</ShortName>
+ <LongName>green</LongName>
+ <Description>Green Random Early Discard Configuration</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_red</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>yellow</ShortName>
+ <LongName>yellow</LongName>
+ <Description>Yellow Random Early Discard Configuration</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_red</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>red</ShortName>
+ <LongName>red</LongName>
+ <Description>Red Random Early Discard Configuration</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_red</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ </ClassifiedStructures>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>tm_bac_type</ShortName>
+ <LongName>tm_bac_type</LongName>
+ <Description>Buffer Admission Control Type</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>taildrop</ShortName>
+ <LongName>taildrop</LongName>
+ <Description>Taildrop </Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>wtaildrop</ShortName>
+ <LongName>wtaildrop</LongName>
+ <Description>Weighted taildrop</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>red</ShortName>
+ <LongName>red</LongName>
+ <Description>Random Early Discard</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>wred</ShortName>
+ <LongName>wred</LongName>
+ <Description>Weighted Random Early Discard</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>tm_creation_mode</ShortName>
+ <LongName>tm_creation_mode</LongName>
+ <Description>TM Creation Mode</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>manual</ShortName>
+ <LongName>manual</LongName>
+ <Description>tm object created manually</Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>auto</ShortName>
+ <LongName>auto</LongName>
+ <Description>tm object created automatically</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>tm_priority</ShortName>
+ <LongName>tm_priority</LongName>
+ <Description>Scheduling Priority</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>tm_queue_id</ShortName>
+ <LongName>tm_queue_id</LongName>
+ <Description>Queue ID</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>tm_queue_ref</ShortName>
+ <LongName>tm_queue_ref</LongName>
+ <Description>Queue Reference</Description>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>sched_id</ShortName>
+ <LongName>Scheduler ID</LongName>
+ <Description>Scheduler (tm_sched) ID</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>queue_id</ShortName>
+ <LongName>Queue ID</LongName>
+ <Description>Queue ID</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_queue_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>tm_red</ShortName>
+ <LongName>tm_red</LongName>
+ <Description>Random Early Discard Configuration</Description>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>min_threshold</ShortName>
+ <LongName>min_threshold</LongName>
+ <Description>Min threshold in percent of max queue size</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>percent</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>max_threshold</ShortName>
+ <LongName>max_threshold</LongName>
+ <Description>Max threshold in percent of max queue size</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>percent</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>max_probability</ShortName>
+ <LongName>max_probability</LongName>
+ <Description>Discard probability for occupancy between min_threshold and max_threshold</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>percent</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>tm_sched_child_type</ShortName>
+ <LongName>tm_sched_child_type</LongName>
+ <Description>Scheduling Level for the Children TM </Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>queue</ShortName>
+ <LongName>queue</LongName>
+ <Description>Queue-level scheduler</Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>sched</ShortName>
+ <LongName>sched</LongName>
+ <Description>Scheduler-level scheduler</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>tm_sched_dir</ShortName>
+ <LongName>tm_sched_dir</LongName>
+ <Description>Traffic Direction</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>us</ShortName>
+ <LongName>upstream</LongName>
+ <Description>Upstream</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>ds</ShortName>
+ <LongName>downstream</LongName>
+ <Description>Downstream</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>tm_sched_id</ShortName>
+ <LongName>tm_sched_id</LongName>
+ <Description>TM Scheduler ID</Description>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Constants>
+ <AliasConstantEntry>
+ <Label>
+ <ShortName>unknown</ShortName>
+ <LongName>Unknown</LongName>
+ </Label>
+ <Value>65535</Value>
+ </AliasConstantEntry>
+ </Constants>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>tm_sched_id_index</ShortName>
+ <LongName>tm node id index</LongName>
+ </Label>
+ <BaseType>
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <MinimumValue>0</MinimumValue>
+ <MaximumValue>2048</MaximumValue>
+ </CustomType>
+ <CustomType Type="CustomTypeClassifiedStructure">
+ <Label>
+ <ShortName>tm_sched_owner</ShortName>
+ <LongName>tm_sched_owner</LongName>
+ <Description>TM Scheduler Owner</Description>
+ </Label>
+ <CommonFields>
+ <Field>
+ <Label>
+ <ShortName>type</ShortName>
+ <LongName>type</LongName>
+ <Description>Owner type</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_owner_type</ShortName>
+ </FieldType>
+ </Field>
+ </CommonFields>
+ <ClassifierFieldName>type</ClassifierFieldName>
+ <ClassifiedStructures>
+ <ClassifiedStructure>
+ <ClassifierValue>interface</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>intf_type</ShortName>
+ <LongName>intf_type</LongName>
+ <Description>Interface Type</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>intf_id</LongName>
+ <Description>Interface ID</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>sub_term</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>intf_id</LongName>
+ <Description>PON interface id</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>sub_term_id</LongName>
+ <Description>Subscriber terminal ID</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>agg_port</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>intf_id</LongName>
+ <Description>PON interface id</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>sub_term_id</LongName>
+ <Description>Subscriber terminal id</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>agg_port_id</ShortName>
+ <LongName>agg_port_id</LongName>
+ <Description>Aggregation port id</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>aggregation_port_id</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>uni</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>intf_id</LongName>
+ <Description>PON interface id</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>sub_term_id</LongName>
+ <Description>Subscriber terminal id</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>index</ShortName>
+ <LongName>index</LongName>
+ <Description>Index at subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ <ClassifiedStructure>
+ <ClassifierValue>virtual</ClassifierValue>
+ <EmbeddedStructure>
+ <Label>
+ <ShortName></ShortName>
+ <LongName></LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>index</ShortName>
+ <LongName>index</LongName>
+ <Description>Owner index</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </EmbeddedStructure>
+ </ClassifiedStructure>
+ </ClassifiedStructures>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>tm_sched_owner_type</ShortName>
+ <LongName>tm_scheduler_owner_type</LongName>
+ <Description>TM Scheduler Owner Type</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>undefined</ShortName>
+ <LongName>undefined</LongName>
+ <Description>Undefined</Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>interface</ShortName>
+ <LongName>interface</LongName>
+ <Description>Interface</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>sub_term</ShortName>
+ <LongName>subs_term</LongName>
+ <Description>Subscriber terminal</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>agg_port</ShortName>
+ <LongName>agg_port</LongName>
+ <Description>TM scheduler is owned by aggregation port</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>uni</ShortName>
+ <LongName>uni</LongName>
+ <Description>TM scheduler is owned by UNI port</Description>
+ </Label>
+ <Value>4</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>virtual</ShortName>
+ <LongName>virtual</LongName>
+ <Description>Other unspecified owner</Description>
+ </Label>
+ <Value>5</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>tm_sched_parent</ShortName>
+ <LongName>tm_sched_parent</LongName>
+ <Description>Scheduling Parent Connect Point</Description>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>sched_id</ShortName>
+ <LongName>sched_id</LongName>
+ <Description>Parent scheduler id</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>priority</ShortName>
+ <LongName>priority</LongName>
+ <Description>Priority</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_priority</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>weight</ShortName>
+ <LongName>weight</LongName>
+ <Description>Weight</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_weight</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>tm_sched_type</ShortName>
+ <LongName>tm_sched_type</LongName>
+ <Description>Scheduler Type</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>none</ShortName>
+ <LongName>none</LongName>
+ <Description>NO scheduling</Description>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>wfq</ShortName>
+ <LongName>wfq</LongName>
+ <Description>Weighted Fair Queue</Description>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>sp</ShortName>
+ <LongName>sp</LongName>
+ <Description>Strict Priority</Description>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>sp_wfq</ShortName>
+ <LongName>sp_wfq</LongName>
+ <Description>Hybrid SP + WFQ</Description>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>tm_shaping</ShortName>
+ <LongName>tm_shaping</LongName>
+ <Description>Shaping Parameters</Description>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>sbr</ShortName>
+ <LongName>sbr</LongName>
+ <Description>Sustained Bit Rate (kbps)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>pbr</ShortName>
+ <LongName>pbr</LongName>
+ <Description>Peak Bit Rate (kbps)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>burst</ShortName>
+ <LongName>burst</LongName>
+ <Description>Max Burst Bytes at Peak Bit Rate</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeStructure">
+ <Label>
+ <ShortName>tm_tcont_sla</ShortName>
+ <LongName>tm_tcont_sla</LongName>
+ <Description>ITU-PON Extended SLA Parameters</Description>
+ </Label>
+ <Options>PresenceMask</Options>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>extra_bw_elig</ShortName>
+ <LongName>extra_bw_elig</LongName>
+ <Description>Extra BW eligibility type</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>extra_bw_eligibility_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>nrt_cbr</ShortName>
+ <LongName>nrt_cbr</LongName>
+ <Description>NRT CBR</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rt_cbr</ShortName>
+ <LongName>rt_cbr</LongName>
+ <Description>RT_CBR</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rt_profile</ShortName>
+ <LongName>rt_profile</LongName>
+ <Description>RT Profile</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>nrt_profile</ShortName>
+ <LongName>key:</LongName>
+ <Description>NRT Profile</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </CustomType>
+ <CustomType Type="CustomTypeAlias">
+ <Label>
+ <ShortName>tm_weight</ShortName>
+ <LongName>tm_weight</LongName>
+ <Description>Scheduling Weight</Description>
+ </Label>
+ <BaseType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ </CustomType>
+ <CustomType Type="CustomTypeEnum">
+ <Label>
+ <ShortName>trx_type</ShortName>
+ <LongName>Transceiver types</LongName>
+ <Description>Transceiver types</Description>
+ </Label>
+ <BaseType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </BaseType>
+ <Entries>
+ <EnumEntry>
+ <Label>
+ <ShortName>gpon_sps_43_48</ShortName>
+ <LongName>gpon_sps_43_48</LongName>
+ </Label>
+ <Value>0</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>gpon_sps_sog_4321</ShortName>
+ <LongName>gpon_sps_sog_4321</LongName>
+ </Label>
+ <Value>1</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>gpon_lte_3680_m</ShortName>
+ <LongName>gpon_lte_3680_m</LongName>
+ </Label>
+ <Value>2</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>gpon_source_photonics</ShortName>
+ <LongName>gpon_source_photonics</LongName>
+ </Label>
+ <Value>3</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>gpon_lte_3680_p</ShortName>
+ <LongName>gpon_lte_3680_p</LongName>
+ </Label>
+ <Value>4</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>xgpon_lth_7222_pc</ShortName>
+ <LongName>xgpon_lth_7222_pc</LongName>
+ </Label>
+ <Value>5</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>xgpon_lth_7226_pc</ShortName>
+ <LongName>xgpon_lth_7226_pc</LongName>
+ </Label>
+ <Value>6</Value>
+ </EnumEntry>
+ <EnumEntry>
+ <Label>
+ <ShortName>xgpon_lth_5302_pc</ShortName>
+ <LongName>xgpon_lth_5302_pc</LongName>
+ </Label>
+ <Value>7</Value>
+ </EnumEntry>
+ </Entries>
+ </CustomType>
+ </CustomTypes>
+ <OmObjects>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>access_terminal</ShortName>
+ <LongName>BAL Access Terminal</LongName>
+ <Description>BAL Access Terminal Object</Description>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>access_term_id</ShortName>
+ <LongName>access_term_id</LongName>
+ <Description>Reserved (set to 0)</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>access_id</ShortName>
+ </FieldType>
+ <DefaultValue>1</DefaultValue>
+ <MinimumValue>1</MinimumValue>
+ <MaximumValue>1</MaximumValue>
+ <Options>Reserved, IsInstanceNumber</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Operational status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>iwf_mode</ShortName>
+ <LongName>Interworking function mode</LongName>
+ <Description>The interworking mode</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>iwf_mode</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Access Terminal Indication</LongName>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Current administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Current operational status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>iwf_mode</ShortName>
+ <LongName>Interworking function mode</LongName>
+ <Description>The interworking mode</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>iwf_mode</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>flow</ShortName>
+ <LongName>BAL Flow</LongName>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Operational status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>access_int_id</ShortName>
+ <LongName>Access Interface ID</LongName>
+ <Description>The ID of the subscriber side interface; i.e. PON</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>network_int_id</ShortName>
+ <LongName>Network Interface ID</LongName>
+ <Description>The ID of the network side interface; i.e. NNI</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>Subscriber Terminal ID</LongName>
+ <Description>The ID of the subsccriber terminal device</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_uni_idx</ShortName>
+ <LongName>Subscriber Terminal uni port index</LongName>
+ <Description>The index of the subsccriber terminal uni port the flow is related to</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port_id</ShortName>
+ <LongName>Service Port ID</LongName>
+ <Description>The ID of the service port (for GPON/XGPON - GEM ID)</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>agg_port_id</ShortName>
+ <LongName>Aggregate port ID</LongName>
+ <Description>The ID of the aggregate port (for GPON/XGPON - ALLOC ID)</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>aggregation_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>resolve_mac</ShortName>
+ <LongName>Resolve mac</LongName>
+ <Description>A flag indicating if the MAC address table should be used in DS GEM resolution</Description>
+ </Label>
+ <FieldType Type="FieldTypeBoolean" />
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>classifier</ShortName>
+ <LongName>Classifier</LongName>
+ <Description>The classifier for this flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>classifier</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>action</ShortName>
+ <LongName>Action</LongName>
+ <Description>The action associated with the flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>action</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sla</ShortName>
+ <LongName>SLA</LongName>
+ <Description>SLA parameters for this flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sla</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>cookie</ShortName>
+ <LongName>Cookie</LongName>
+ <Description>Application cookie</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>cookie</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>priority</ShortName>
+ <LongName>Priority</LongName>
+ <Description>Priority for this flow in case of multiple match.
+Higher value precednece over lower value.</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ <MinimumValue>1</MinimumValue>
+ <MaximumValue>255</MaximumValue>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>group_id</ShortName>
+ <LongName>Group ID</LongName>
+ <Description>RW - The multicast group associated with this flow, valid for type MULTICAST only</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>group_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>queue</ShortName>
+ <LongName>Egress queue</LongName>
+ <Description>Egress queue</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_queue_ref</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>flow_id</ShortName>
+ <LongName>Flow ID</LongName>
+ <Description>The ID of the flow object instance being referenced</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>flow_id</ShortName>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_type</ShortName>
+ <LongName>Flow type</LongName>
+ <Description>The type of the flow, Upstream, Downstream, Broadcast or Multicast</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>flow_type</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>stat</ShortName>
+ <LongName>stat</LongName>
+ </Label>
+ <Type>Statistics</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>rx_packets</ShortName>
+ <LongName>Received packets</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rx_bytes</ShortName>
+ <LongName>Received bytes</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tx_packets</ShortName>
+ <LongName>Transmitted packets</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tx_bytes</ShortName>
+ <LongName>Transmitted bytes</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Flow Indication</LongName>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Operational Status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>access_int_id</ShortName>
+ <LongName>Access interface ID</LongName>
+ <Description>The ID of the subscriber side interface; i.e. PON</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>network_int_id</ShortName>
+ <LongName>Network Interface ID</LongName>
+ <Description>The ID of the network side interface; i.e. NNI</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>Subscriber terminal ID</LongName>
+ <Description>The ID of the subsccriber terminal device</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port_id</ShortName>
+ <LongName>Service port ID</LongName>
+ <Description>The ID of the service port (for GPON/XGPON - GEM ID)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>agg_port_id</ShortName>
+ <LongName>Aggregate port ID</LongName>
+ <Description>The ID of the aggregate port (for GPON/XGPON - ALLOC ID)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>resolve_mac</ShortName>
+ <LongName>Resolve mac</LongName>
+ <Description>A flag indicating if the MAC address table should be used in DS GEM resolution</Description>
+ </Label>
+ <FieldType Type="FieldTypeBoolean" />
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>base_tc_id</ShortName>
+ <LongName>Base TCONT ID</LongName>
+ <Description>The base index of the TC object(s) to be used for this flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>classifier</ShortName>
+ <LongName>Classifier</LongName>
+ <Description>The classifier for this flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>classifier</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>action</ShortName>
+ <LongName>Action</LongName>
+ <Description>The action associated with the flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>action</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sla</ShortName>
+ <LongName>SLA</LongName>
+ <Description>SLA parameters for this flow</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sla</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>cookie</ShortName>
+ <LongName>Cookie</LongName>
+ <Description>Application cookie</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>priority</ShortName>
+ <LongName>Priority</LongName>
+ <Description>Priority for this flow in case of multiple match.
+Higher value precednece over lower value.</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ <MinimumValue>1</MinimumValue>
+ <MaximumValue>255</MaximumValue>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>group</ShortName>
+ <LongName>BAL Group</LongName>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>members_cmd</ShortName>
+ <LongName>Membership operation commands</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>group_member_cmd</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>members</ShortName>
+ <LongName>Member</LongName>
+ <Description>The list of members associated with this group</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>group_member_info</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>cookie</ShortName>
+ <LongName>Application cookie</LongName>
+ <Description>Application cookie</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>cookie</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flows</ShortName>
+ <LongName>List of flows associated with the group </LongName>
+ <Description>List of flows associated with this group</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>flow_id</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ <MinimumLength>0</MinimumLength>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>owner</ShortName>
+ <LongName>Owner of the group</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>group_owner</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>group_id</ShortName>
+ <LongName>Group ID</LongName>
+ <Description>The ID of the group object instance being referenced</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>group_id</ShortName>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>interface</ShortName>
+ <LongName>BAL Interface</LongName>
+ <Description>BAL interface object</Description>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>intf_id</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_type</ShortName>
+ <LongName>intf_type</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_type</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Operational status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>min_data_agg_port_id</ShortName>
+ <LongName>Minimum aggregate port ID</LongName>
+ <Description>The minimum agg_port_id that is allowed in the system</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>aggregation_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>min_data_svc_port_id</ShortName>
+ <LongName>Minimum service port ID</LongName>
+ <Description>The minimum svc_port_id that is allowed in the system</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>transceiver_type</ShortName>
+ <LongName>Transceiver type</LongName>
+ <Description>The transceiver type used on an interface</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>trx_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ds_miss_mode</ShortName>
+ <LongName>Downstream unknown packet action</LongName>
+ <Description>Defines the action to take for unknown downstream packets</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>ds_miss_mode</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>mtu</ShortName>
+ <LongName>MTU</LongName>
+ <Description>The MTU for an interface</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_control</ShortName>
+ <LongName>Flow control</LongName>
+ <Description>Flow control enable or disable</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>control</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ds_tm</ShortName>
+ <LongName>Downstream scheduler and shaper</LongName>
+ <Description>Downstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>us_tm</ShortName>
+ <LongName>Upstream scheduler and shaper</LongName>
+ <Description>Upstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id_list</ShortName>
+ <LongName>Sub-term id list</LongName>
+ <Description>A list of subscriber terminal ids configured on this interface</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>stat</ShortName>
+ <LongName>stat</LongName>
+ </Label>
+ <Type>Statistics</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>rx_packets</ShortName>
+ <LongName>Recieved packets</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rx_bytes</ShortName>
+ <LongName>Received bytes</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tx_packets</ShortName>
+ <LongName>Transmitted packets</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tx_bytes</ShortName>
+ <LongName>Transmitted bytes</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Interface Indication</LongName>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Current administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Current operational state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>min_data_agg_port_id</ShortName>
+ <LongName>Minimum aggregate port ID</LongName>
+ <Description>The minimum agg_port_id that is allowed in the system</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>min_data_svc_port_id</ShortName>
+ <LongName>Minimum service port ID</LongName>
+ <Description>The minimum svc_port_id that is allowed in the system</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>transceiver_type</ShortName>
+ <LongName>Transceiver type</LongName>
+ <Description>The transceiver type used on an interface</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>trx_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ds_miss_mode</ShortName>
+ <LongName>Downstream unknown packet action</LongName>
+ <Description>Defines the action to take for DS unknown packets</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>ds_miss_mode</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>mtu</ShortName>
+ <LongName>MTU</LongName>
+ <Description>The MTU for an interface</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_control</ShortName>
+ <LongName>Flow control</LongName>
+ <Description>Flow control enable or disable</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>control</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ds_tm</ShortName>
+ <LongName>Downstream scheduler and shaper</LongName>
+ <Description>Downstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>us_tm</ShortName>
+ <LongName>Upstream scheduler and shaper</LongName>
+ <Description>Upstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>packet</ShortName>
+ <LongName>packet</LongName>
+ <Description>Packet that can be transmitted or received</Description>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>flow_id</ShortName>
+ <LongName>Flow Id</LongName>
+ <Description>N/A for sending a packet</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>flow_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_type</ShortName>
+ <LongName>Flow Type</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>flow_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>Interface ID</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_type</ShortName>
+ <LongName>Interface Type</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port</ShortName>
+ <LongName>Service Port</LongName>
+ <Description>N/A for sending a packet</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_cookie</ShortName>
+ <LongName>Flow Cookie</LongName>
+ <Description>N/A for sending a packet</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>cookie</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>pkt</ShortName>
+ <LongName>Packet Data</LongName>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>reserved</ShortName>
+ <LongName>Reserved key field</LongName>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>packet_send_dest</ShortName>
+ <LongName>Packet destination</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>dest</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Packet indication</LongName>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>flow_id</ShortName>
+ <LongName>Flow Id</LongName>
+ <Description>N/A for sending a packet</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>flow_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_type</ShortName>
+ <LongName>Flow Type</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>flow_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>Interface ID</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_type</ShortName>
+ <LongName>Interface Type</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port</ShortName>
+ <LongName>Service Port</LongName>
+ <Description>N/A for sending a packet</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>flow_cookie</ShortName>
+ <LongName>Flow Cookie</LongName>
+ <Description>N/A for sending a packet</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>cookie</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>pkt</ShortName>
+ <LongName>Packet Data</LongName>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>subscriber_terminal</ShortName>
+ <LongName>BAL Subscriber Terminal</LongName>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>sub_term_id</ShortName>
+ <LongName>sub_term_id</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>sub_id</ShortName>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>intf_id</ShortName>
+ <LongName>intf_id</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>intf_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Operational status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>serial_number</ShortName>
+ <LongName>Serial number</LongName>
+ <Description>The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>serial_number</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>password</ShortName>
+ <LongName>Password</LongName>
+ <Description>The password of a GPON subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>password</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>registration_id</ShortName>
+ <LongName>Registration id</LongName>
+ <Description>ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>registration_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port_id</ShortName>
+ <LongName>Service port ID</LongName>
+ <Description>The management service port ID (for PON, the ONU ID)</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>mac_address</ShortName>
+ <LongName>MAC address</LongName>
+ <Description>The Ethernet MAC address of an EPON subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeWellKnown">
+ <WellKnownType>MacAddress</WellKnownType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ds_tm</ShortName>
+ <LongName>Downstream scheduler and shaper</LongName>
+ <Description>Downstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>us_tm</ShortName>
+ <LongName>Upstream scheduler and shaper</LongName>
+ <Description>Upstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port_id_list</ShortName>
+ <LongName>svc_port_id list</LongName>
+ <Description>A list of bearer traffic svc_port_ids associated with this subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>service_port_id</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>agg_port_id_list</ShortName>
+ <LongName>agg_port_id list</LongName>
+ <Description>A list of aggr_port_ids associated with this subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>aggregation_port_id</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>stat</ShortName>
+ <LongName>stat</LongName>
+ </Label>
+ <Type>Statistics</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>rx_packets</ShortName>
+ <LongName>Received packets</LongName>
+ <Description>Received packets on specified object</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rx_bytes</ShortName>
+ <LongName>Received bytes</LongName>
+ <Description>Received bytes on specified object</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tx_packets</ShortName>
+ <LongName>Transmitted packets</LongName>
+ <Description>Transmitted packets on specified object</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tx_bytes</ShortName>
+ <LongName>Transmitted bytes</LongName>
+ <Description>Transmittted bytes on specified object</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Subscriber Terminal Indication</LongName>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>admin_state</ShortName>
+ <LongName>Administrative state</LongName>
+ <Description>Current administrative state</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>state</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>oper_status</ShortName>
+ <LongName>Operational status</LongName>
+ <Description>Current operational status</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>status</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>serial_number</ShortName>
+ <LongName>Serial number</LongName>
+ <Description>The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>serial_number</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>password</ShortName>
+ <LongName>Password</LongName>
+ <Description>The password of a GPON subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>password</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>registration_id</ShortName>
+ <LongName>Registration id</LongName>
+ <Description>ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>registration_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>svc_port_id</ShortName>
+ <LongName>Service port ID</LongName>
+ <Description>The service port ID (for PON, the ONU ID)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>2</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>mac_address</ShortName>
+ <LongName>MAC address</LongName>
+ <Description>The Ethernet MAC address of an epon subscriber terminal</Description>
+ </Label>
+ <FieldType Type="FieldTypeWellKnown">
+ <WellKnownType>MacAddress</WellKnownType>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ds_tm</ShortName>
+ <LongName>Downstream scheduler and shaper</LongName>
+ <Description>Downstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>us_tm</ShortName>
+ <LongName>Upstream scheduler and shaper</LongName>
+ <Description>Upstream scheduler and shaper</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>tm_queue</ShortName>
+ <LongName>tm_queue</LongName>
+ <Description>Transmit queue</Description>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>sched_id</ShortName>
+ <LongName>sched_id</LongName>
+ <Description>Scheduler that owns the queue</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sched_dir</ShortName>
+ <LongName>sched dir</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_dir</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>id</ShortName>
+ <LongName>id</LongName>
+ <Description>Queue id</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_queue_id</ShortName>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>priority</ShortName>
+ <LongName>priority</LongName>
+ <Description>Scheduling priority</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_priority</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>weight</ShortName>
+ <LongName>weight</LongName>
+ <Description>Scheduling weight</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_weight</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rate</ShortName>
+ <LongName>rate</LongName>
+ <Description>Rate shaping parameters</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_shaping</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>bac</ShortName>
+ <LongName>bac</LongName>
+ <Description>Buffer admission control</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_bac</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>creation_mode</ShortName>
+ <LongName>creation_mode</LongName>
+ <Description>Creation mode</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_creation_mode</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>ref_count</ShortName>
+ <LongName>ref_count</LongName>
+ <Description>reference count (flows)</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>stat</ShortName>
+ <LongName>stat</LongName>
+ </Label>
+ <Type>Statistics</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>packets_ok</ShortName>
+ <LongName>packets_ok</LongName>
+ <Description>Packets transmitted succewssfully</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>bytes_ok</ShortName>
+ <LongName>bytes_ok</LongName>
+ <Description>Bytes transmitted successfully</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>packets_discarded</ShortName>
+ <LongName>packets_discarded</LongName>
+ <Description>Packets discarded</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>bytes_discarded</ShortName>
+ <LongName>bytes_discarded</LongName>
+ <Description>Bytes discarded</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>8</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Tm Queue Indication</LongName>
+ <Description>Tm Queue Indication</Description>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>ret</ShortName>
+ <LongName>ret</LongName>
+ <Description>ret</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ <ObjectModel.OmObject>
+ <Label>
+ <ShortName>tm_sched</ShortName>
+ <LongName>tm_sched</LongName>
+ <Description>Scheduling node</Description>
+ </Label>
+ <Groups>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>key</ShortName>
+ <LongName>key</LongName>
+ </Label>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>dir</ShortName>
+ <LongName>dir</LongName>
+ <Description>Traffic direction</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_dir</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>id</ShortName>
+ <LongName>id</LongName>
+ <Description>ID</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </FieldType>
+ <Options>IsInstanceNumber</Options>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>cfg</ShortName>
+ <LongName>cfg</LongName>
+ </Label>
+ <Type>Configuration</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>owner</ShortName>
+ <LongName>owner</LongName>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_owner</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sched_type</ShortName>
+ <LongName>type</LongName>
+ <Description>Scheduler type</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sched_parent</ShortName>
+ <LongName>parent</LongName>
+ <Description>Scheduling parameters for parent scheduler</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_parent</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sched_child_type</ShortName>
+ <LongName>child_type</LongName>
+ <Description>Scheduling level for children tm </Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_sched_child_type</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>rate</ShortName>
+ <LongName>rate</LongName>
+ <Description>Rate shaping parameters</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_shaping</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>tcont_sla</ShortName>
+ <LongName>tcont_sla</LongName>
+ <Description>Additional SLA parameters for agg_port owner</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_tcont_sla</ShortName>
+ </FieldType>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>creation_mode</ShortName>
+ <LongName>creation_mode</LongName>
+ <Description>Creation mode</Description>
+ </Label>
+ <FieldType Type="FieldTypeReference">
+ <ShortName>tm_creation_mode</ShortName>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>queues</ShortName>
+ <LongName>queues</LongName>
+ <Description>Subsidiary queues</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>tm_queue_id</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>sub_scheds</ShortName>
+ <LongName>sub_scheds</LongName>
+ <Description>Subsidiary schedulers</Description>
+ </Label>
+ <FieldType Type="FieldTypeList">
+ <ElementType Type="FieldTypeReference">
+ <ShortName>tm_sched_id</ShortName>
+ </ElementType>
+ <AutoCountFieldType>
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </AutoCountFieldType>
+ </FieldType>
+ <Options>ReadOnly</Options>
+ </Field>
+ <Field>
+ <Label>
+ <ShortName>num_priorities</ShortName>
+ <LongName>num_priorities</LongName>
+ <Description>Max number of strict priority scheduling elements</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>1</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ <ObjectModel.OmGroup>
+ <Label>
+ <ShortName>ind</ShortName>
+ <LongName>Tm Sched Indication</LongName>
+ <Description>Tm Sched Indication</Description>
+ </Label>
+ <Type>Indication</Type>
+ <Fields>
+ <Field>
+ <Label>
+ <ShortName>ret</ShortName>
+ <LongName>ret</LongName>
+ <Description>ret</Description>
+ </Label>
+ <FieldType Type="FieldTypeNumber">
+ <Width>4</Width>
+ <Signed>False</Signed>
+ </FieldType>
+ </Field>
+ </Fields>
+ </ObjectModel.OmGroup>
+ </Groups>
+ </ObjectModel.OmObject>
+ </OmObjects>
+</ElementSet>
\ No newline at end of file
diff --git a/bal_release/src/lib/common/placeholder b/bal_release/src/lib/common/placeholder
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/bal_release/src/lib/common/placeholder
diff --git a/bal_release/src/lib/libbalapi/Makefile b/bal_release/src/lib/libbalapi/Makefile
new file mode 100644
index 0000000..79fea84
--- /dev/null
+++ b/bal_release/src/lib/libbalapi/Makefile
@@ -0,0 +1,38 @@
+###############################################################################
+#
+# <: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 = bal_api
+MOD_TYPE = lib
+MOD_DEPS = common_include dev_log maple_sdk balobjmsg
+ifeq ("$(BAL_MONOLITHIC)", "y")
+MOD_DEPS += bal_core
+endif
+
+srcs = bal_api.c bal_api_worker.c
diff --git a/bal_release/src/lib/libbalapi/bal_api.c b/bal_release/src/lib/libbalapi/bal_api.c
new file mode 100644
index 0000000..4374fd2
--- /dev/null
+++ b/bal_release/src/lib/libbalapi/bal_api.c
@@ -0,0 +1,658 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_api.c
+ * @brief The BAL Public API
+ *
+ * @addtogroup api
+ */
+
+/*@{*/
+
+/* Project includes */
+#include "bal_api.h"
+#include "bal_msg.h"
+#include "bal_api_worker.h"
+#include "bal_obj_msg_pack_unpack.h"
+#ifdef BAL_MONOLITHIC
+#include <bal_worker.h>
+#endif
+
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+
+/*
+ * @brief The logging device id for the BAL public API
+ */
+dev_log_id log_id_public_api;
+#endif
+
+/*
+ * @brief The global mgmt queues
+ *
+ * These are the queues through which the BAL API communicates with
+ * the core, and vice versa.
+ */
+static bcmos_msg_queue balapi_rsp_queue;
+static bcmos_msg_queue balapi_to_core_queue;
+
+bcmos_msg_queue *p_balapi_rsp_queue;
+bcmos_msg_queue *p_balapi_to_core_queue;
+
+static bcmos_mutex balapi_lock;
+static uint32_t balapi_exchange_id;
+static STAILQ_HEAD(pending_req_list, bcmos_msg) pending_req_list;
+
+static bcmos_task api_rsp_rx_thread;
+static int _bal_ipc_api_rx_handler(long data);
+
+/* Rx polling timeout (us) */
+#define BAL_API_RX_POLL_TIMEOUT 100000
+
+/*****************************************************************************
+ * Initialize the BAL Public API internal data structures
+ *****************************************************************************/
+bcmos_errno bcmbal_api_init(const char *balapi_mgmt_ip_port,
+ const char *core_mgmt_ip_port)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+ bcmos_msg_queue_parm msg_q_p = {};
+ bcmos_task_parm task_p = {};
+
+#ifdef ENABLE_LOG
+ log_id_public_api = bcm_dev_log_id_register("BAL_API", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(log_id_public_api == DEV_LOG_INVALID_ID);
+#endif
+
+ do
+ {
+ STAILQ_INIT(&pending_req_list);
+
+ ret = bcmos_mutex_create(&balapi_lock, 0, "bal_api");
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API protection mutex\n");
+ break;
+ }
+
+ /* Create BAL API RX management queue - the BAL Public API
+ * exchanges management messages with the BAL core using this queue.
+ */
+ msg_q_p.name = "balapi_mgmt_q";
+ if (NULL != balapi_mgmt_ip_port)
+ {
+ msg_q_p.local_ep_address = balapi_mgmt_ip_port;
+ msg_q_p.remote_ep_address = NULL;
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
+ }
+ else
+ {
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_LOCAL;
+ }
+ ret = bcmos_msg_queue_create(&balapi_rsp_queue, &msg_q_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API mgmt queue\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ p_balapi_rsp_queue = &balapi_rsp_queue;
+#ifdef BAL_MONOLITHIC
+ if (NULL == balapi_mgmt_ip_port)
+ p_bal_core_to_api_queue = p_balapi_rsp_queue;
+#endif
+
+ /* Create queue for sending API requests to the core. Only do it if API and core interact via UDP
+ */
+ if (NULL != core_mgmt_ip_port)
+ {
+ msg_q_p.name = "balapi_to_core_q";
+ msg_q_p.local_ep_address = NULL;
+ msg_q_p.remote_ep_address = core_mgmt_ip_port;
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
+
+ ret = bcmos_msg_queue_create(&balapi_to_core_queue, &msg_q_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API mgmt queue\n");
+ ret = BCM_ERR_INTERNAL;
+ break;
+ }
+ p_balapi_to_core_queue = &balapi_to_core_queue;
+ }
+
+ /* Create BAL API RX thread */
+ task_p.name = "ipc_api_rsp_rx_thread";
+ task_p.priority = TASK_PRIORITY_IPC_RX;
+ task_p.handler = _bal_ipc_api_rx_handler;
+ task_p.data = (long)p_balapi_rsp_queue;
+
+ ret = bcmos_task_create(&api_rsp_rx_thread, &task_p);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API response RX thread\n");
+ break;
+ }
+
+ /*
+ * Initialize the BAL Public API backend worker and rx threads. These
+ * threads are used to receive asynchronous indications from the core.
+ */
+ enable_bal_api_indications(balapi_mgmt_ip_port);
+
+ }
+ while(0);
+
+ return ret;
+}
+
+/*****************************************************************************
+ * Un-initialize the BAL Public API internal data structures
+ *****************************************************************************/
+bcmos_errno bcmbal_api_finish(void)
+{
+ bcmos_task_destroy(&api_rsp_rx_thread);
+ bcmos_msg_queue_destroy(&balapi_rsp_queue);
+ if (p_balapi_to_core_queue == &balapi_to_core_queue)
+ bcmos_msg_queue_destroy(&balapi_to_core_queue);
+
+ bal_api_indications_finish();
+
+ return BCM_ERR_OK;
+}
+
+/* Find pending request matching response */
+static bal_comm_msg_hdr *_bal_api_get_request_by_ex_id(uint32_t ex_id)
+{
+ bcmos_msg *req_msg, *tmp_msg;
+ bal_comm_msg_hdr *comm_hdr = NULL;
+
+ STAILQ_FOREACH_SAFE(req_msg, &pending_req_list, next, tmp_msg)
+ {
+ comm_hdr = bcmbal_bal_hdr_get_by_bcmos_hdr(req_msg);
+ if (comm_hdr->ex_id == ex_id)
+ {
+ STAILQ_REMOVE(&pending_req_list, req_msg, bcmos_msg, next);
+ break;
+ }
+ }
+ return req_msg ? comm_hdr : NULL;
+}
+
+/* Check if any pending request timed out */
+static void _bal_api_check_req_timeout(void)
+{
+ bcmos_msg *req_msg, *tmp_msg;
+ bal_comm_msg_hdr *comm_hdr;
+ bcmbal_obj *req_obj;
+ uint32_t ts = bcmos_timestamp();
+
+ STAILQ_FOREACH_SAFE(req_msg, &pending_req_list, next, tmp_msg)
+ {
+ comm_hdr = bcmbal_bal_hdr_get_by_bcmos_hdr(req_msg);
+ if (ts - comm_hdr->timestamp >= BCMBAL_MSG_TIMEOUT_1_SEC)
+ {
+ STAILQ_REMOVE(&pending_req_list, req_msg, bcmos_msg, next);
+ req_obj = (bcmbal_obj *)bcmbal_payload_ptr_get(comm_hdr);
+ /* Release pending API call */
+ req_obj->status = BCM_ERR_TIMEOUT;
+ BCM_LOG(DEBUG, log_id_public_api, "Timing out request %p\n", comm_hdr);
+ bcmos_sem_post(&comm_hdr->sem);
+ }
+ }
+}
+
+/* API response handler */
+static int _bal_ipc_api_rx_handler(long data)
+{
+ static uint32_t last_timeout_check_ts;
+ bcmos_msg_queue *rxq = (bcmos_msg_queue *)data;
+ bcmos_task *my_task = bcmos_task_current();
+ bcmos_msg *msg;
+ bcmos_errno ret = BCM_ERR_OK;
+ uint32_t ex_id;
+ bal_comm_msg_hdr *req;
+ bcmbal_obj *req_obj;
+
+ last_timeout_check_ts = bcmos_timestamp();
+ while (!my_task->destroy_request)
+ {
+ /* Wait for response */
+ msg = NULL;
+ req = NULL;
+
+ ret = bcmos_msg_recv(rxq, BAL_API_RX_POLL_TIMEOUT, &msg);
+ if(BCM_ERR_OK != ret && BCM_ERR_TIMEOUT != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "error during bcmos_msg_recv (error:%s)\n", bcmos_strerror(ret));
+ }
+
+ /* Peek exchange id */
+ if (msg)
+ {
+ ret = bcmbal_bal_msg_peek_ex_id(msg, &ex_id);
+ if(BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "bad message. Can't find exchange id (error:%s)\n", bcmos_strerror(ret));
+ bcmos_msg_free(msg);
+ msg = NULL;
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_public_api, "Received message with ex_id=%u\n", ex_id);
+ }
+ }
+
+ /* Now find pending request and also check if any pending request(s) timed out */
+ bcmos_mutex_lock(&balapi_lock);
+ if (msg)
+ {
+ req = _bal_api_get_request_by_ex_id(ex_id);
+ if (NULL == req)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "Request with ex_id=%u is not found. Probably expired. Response discarded\n", ex_id);
+ }
+ else
+ {
+ BCM_LOG(DEBUG, log_id_public_api, "Found request %p\n", req);
+ }
+ }
+ if (bcmos_timestamp() - last_timeout_check_ts >= BCMBAL_MSG_TIMEOUT_1_SEC)
+ {
+ _bal_api_check_req_timeout();
+ last_timeout_check_ts = bcmos_timestamp();
+ }
+ bcmos_mutex_unlock(&balapi_lock);
+
+ /* Got a message. Now unpack it */
+ if (req)
+ {
+ req_obj = (bcmbal_obj *)bcmbal_payload_ptr_get(req);
+ ret = bcmbal_obj_msg_unpack(msg, &req);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Error during message unpack: %s\n", bcmos_strerror(ret));
+ req_obj->status = ret;
+ }
+ /* Release pending API */
+ BCM_LOG(DEBUG, log_id_public_api, "Posting request semaphore for %p\n", req);
+ bcmos_sem_post(&req->sem);
+ }
+
+ if (msg)
+ bcmos_msg_free(msg); /* release packed message. It is no longer needed */
+ }
+
+ my_task->destroyed = BCMOS_TRUE;
+
+ return (BCM_ERR_OK == ret) ? 0 : -EINVAL;
+}
+
+static bcmbal_mgmt_oper_id _bcmbal_obj_to_oper_id(const bcmbal_obj *objinfo)
+{
+ if (objinfo->group == BCMBAL_MGT_GROUP_STAT)
+ {
+ return BCMBAL_MGMT_OPER_ID_GET_STATS;
+ }
+ else if ((objinfo->type & BCMBAL_OBJ_MSG_TYPE_GET))
+ {
+ return BCMBAL_MGMT_OPER_ID_GET;
+ }
+ else if ((objinfo->type & BCMBAL_OBJ_MSG_TYPE_CLEAR))
+ {
+ return BCMBAL_MGMT_OPER_ID_CLEAR;
+ }
+ else
+ {
+ return BCMBAL_MGMT_OPER_ID_SET;
+ }
+}
+
+#define BALAPI_OPER_TIMEOUT (30000000) /* 30 seconds */
+
+static bcmos_errno _bcmbal_oper(bcmbal_obj *objinfo)
+{
+ bal_comm_msg_hdr *comm_hdr = bcmbal_bal_hdr_get(objinfo);
+ bcmos_msg *os_msg;
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /*
+ * Send the message to the core for processing
+ */
+
+ /* Parameter checks */
+ BUG_ON(NULL == objinfo);
+
+ /* Check the magic number to be sure that the object has been properly initialized */
+ if(BCMBAL_OBJ_INIT_VAL != objinfo->obj_init_val)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "Object has not been initialized: must use a BCMBAL INIT macro on the object before calling the BAL API\n");
+ return BCM_ERR_PARM;
+ }
+
+ ret = bcmos_sem_create(&comm_hdr->sem, 0, 0, "api_req");
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Can't create semaphore: %s\n", bcmos_strerror(ret));
+ /* return here. We don't want to destroy semaphore that wasn't created */
+ return ret;
+ }
+
+ do
+ {
+ bcmbal_msg_hdr_set(objinfo,
+ BCMBAL_MGMT_MSG,
+ BAL_MSG_TYPE_REQ,
+ BAL_SUBSYSTEM_PUBLIC_API,
+ objinfo->obj_type,
+ _bcmbal_obj_to_oper_id(objinfo),
+ 0);
+
+ BCM_LOG(DEBUG, log_id_public_api, "about to send %p\n", objinfo);
+
+ bcmos_mutex_lock(&balapi_lock);
+ bcmbal_ex_id_set(objinfo, ++balapi_exchange_id);
+ os_msg = bcmbal_bcmos_hdr_get(objinfo);
+ STAILQ_INSERT_TAIL(&pending_req_list, os_msg, next);
+ bcmos_mutex_unlock(&balapi_lock);
+
+ if (BCM_ERR_OK != (ret = bcmbal_msg_send(p_balapi_to_core_queue, objinfo, BCMOS_MSG_SEND_NO_FREE_ON_ERROR)))
+ {
+ BCM_LOG(ERROR, log_id_public_api, "message send failed with error: %s\n", bcmos_strerror(ret));
+ break;
+ }
+ BCM_LOG(DEBUG, log_id_public_api, "REQ message sent to core\n");
+
+ /*
+ * We've sent the message to the core, now, wait for the response (or timeout)
+ */
+ ret = bcmos_sem_wait(&comm_hdr->sem, BALAPI_OPER_TIMEOUT);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "rsp message receive for failed with error: %s\n",
+ bcmos_strerror(ret));
+ break;
+ }
+ BCM_LOG(DEBUG, log_id_public_api, "RSP message received from core\n");
+
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "failed to process rsp msg\n");
+ break;
+ }
+
+ if(BCM_ERR_OK != objinfo->status)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "remote message command status is: %s\n",
+ bcmos_strerror(objinfo->status));
+ }
+
+ /*
+ * Pass the command status received from the core back to the caller
+ */
+ ret = objinfo->status;
+ }
+ while(0);
+
+ bcmos_sem_destroy(&comm_hdr->sem);
+
+ return ret;
+}
+
+/*****************************************************************************
+ * BAL Public API Set (or modify) command.
+ *****************************************************************************/
+bcmos_errno bcmbal_cfg_set(bcmbal_cfg *objinfo)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_public_api, "BAL PUBLIC API - BCMBAL_SET\n");
+
+ if(BCMBAL_OBJ_ID_PACKET == objinfo->hdr.obj_type)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "unsupported object id detected %d\n", objinfo->hdr.obj_type);
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ }
+ else
+ {
+ objinfo->hdr.type = BCMBAL_OBJ_MSG_TYPE_SET;
+ ret = _bcmbal_oper(&objinfo->hdr);
+ }
+
+ return ret;
+}
+
+#define BCMBAL_MAX_PROXY_PACKET_SIZE (1600)
+
+/*****************************************************************************
+ * BAL Public API Packet Send function.
+ *****************************************************************************/
+bcmos_errno bcmbal_pkt_send(bcmbal_dest dest,
+ const char *packet_to_send,
+ uint16_t packet_len)
+{
+ /* Convert the user packet into a BAL object */
+ bcmbal_packet_cfg *p_packet_obj;
+ bcmbal_packet_key key;
+ bcmbal_u8_list_u32 pkt;
+ bcmos_errno ret;
+
+ BCM_LOG(INFO, log_id_public_api, "BAL PUBLIC API - BCMBAL_SEND to %s\n",
+ (BCMBAL_DEST_TYPE_NNI == dest.type) ? "NNI" : "SUB-TERM");
+
+ if(BCMBAL_MAX_PROXY_PACKET_SIZE < packet_len)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "user packet length (%d) cannot be greater than %d\n",
+ packet_len,
+ BCMBAL_MAX_PROXY_PACKET_SIZE);
+
+ return BCM_ERR_PARM;
+ }
+
+ BCM_LOG(INFO, log_id_public_api, "user packet first 8 bytes %02X%02X%02X%02X%02X%02X%02X%02X\n",
+ packet_to_send[0], packet_to_send[1], packet_to_send[2], packet_to_send[3],
+ packet_to_send[4], packet_to_send[5], packet_to_send[6], packet_to_send[7]);
+
+ /* Set up the object key */
+ key.packet_send_dest = dest;
+
+ /* Allocate room for the packet object including the user packet */
+ p_packet_obj = bcmos_calloc(sizeof(bcmbal_packet_cfg) + packet_len);
+
+ BCMBAL_CFG_INIT(p_packet_obj, packet, key);
+
+ /* Now fill in user packet data into the object */
+ pkt.len = packet_len;
+ pkt.val = (uint8_t *)&p_packet_obj[1];
+ memcpy(pkt.val, packet_to_send, packet_len);
+
+ BCMBAL_CFG_PROP_SET(p_packet_obj, packet, pkt, pkt);
+
+ p_packet_obj->hdr.hdr.type = BCMBAL_OBJ_MSG_TYPE_SET; /* internally packet SEND is modeled as a config SET */
+ ret = _bcmbal_oper(&(p_packet_obj->hdr.hdr));
+ bcmos_free(p_packet_obj);
+
+ return ret;
+}
+
+/*****************************************************************************
+ * BAL Public API Get command.
+ *****************************************************************************/
+bcmos_errno bcmbal_cfg_get(bcmbal_cfg *objinfo)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(DEBUG, log_id_public_api, "BAL PUBLIC API - BCMBAL_GET\n");
+
+ if(BCMBAL_OBJ_ID_PACKET == objinfo->hdr.obj_type)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "unsupported object id detected %d\n", objinfo->hdr.obj_type);
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ }
+ else
+ {
+ objinfo->hdr.type = BCMBAL_OBJ_MSG_TYPE_GET;
+ ret = _bcmbal_oper(&(objinfo->hdr));
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+ * BAL Public API Clear command.
+ *****************************************************************************/
+bcmos_errno bcmbal_cfg_clear(bcmbal_cfg *objinfo)
+{
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BCM_LOG(INFO, log_id_public_api, "BAL PUBLIC API - BCMBAL_CLEAR\n");
+
+ if(BCMBAL_OBJ_ID_PACKET == objinfo->hdr.obj_type)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "unsupported object id detected %d\n", objinfo->hdr.obj_type);
+ ret = BCM_ERR_NOT_SUPPORTED;
+
+ }
+ else
+ {
+ objinfo->hdr.type = BCMBAL_OBJ_MSG_TYPE_CLEAR;
+ ret = _bcmbal_oper(&objinfo->hdr);
+ }
+
+ return ret;
+}
+
+/*****************************************************************************
+ * @brief BAL Public API Get Stats command.
+ *****************************************************************************/
+bcmos_errno bcmbal_stat_get(bcmbal_stat *objinfo)
+{
+
+ /* Parameter checks */
+ BUG_ON(NULL == objinfo);
+
+ /*
+ * @todo Finish the stats function
+ */
+
+ BCM_LOG(ERROR, log_id_public_api, "bal get stats API not supported\n");
+
+ return BCM_ERR_NOT_SUPPORTED;
+}
+
+/*****************************************************************************
+ * BAL Public API indication subscription.
+ *****************************************************************************/
+bcmos_errno bcmbal_subscribe_ind(bcmbal_cb_cfg *cb_cfg)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+
+ /*
+ * The indication subscription function
+ */
+ BCM_LOG(DEBUG, log_id_public_api, "BAL indication subscription for type: %s (%d)\n",
+ bcmbal_objtype_str(cb_cfg->obj_type), cb_cfg->obj_type);
+
+ ret = _manage_api_ind_listener(IND_CB_SUBSCRIBE, cb_cfg);
+
+ return ret;
+}
+
+/*****************************************************************************
+ * BAL Public API indication un-subscription.
+ *****************************************************************************/
+bcmos_errno bcmbal_unsubscribe_ind(bcmbal_cb_cfg *cb_cfg)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BUG_ON(NULL == cb_cfg);
+
+ /*
+ * The indication subscription function
+ */
+ BCM_LOG(DEBUG, log_id_public_api, "BAL indication un-subscription for type: %s (%d)\n",
+ bcmbal_objtype_str(cb_cfg->obj_type), cb_cfg->obj_type);
+
+ ret = _manage_api_ind_listener(IND_CB_UNSUBSCRIBE, cb_cfg);
+
+ return ret;
+}
+
+/*****************************************************************************/
+/**
+ * @brief A function to get the string representation of the interface type
+ *
+ * @param int_type The interface type to get
+ *
+ * @returns const char * A pointer to a string containing the interface type,
+ * or "INVALID", if not a valid type.
+ *
+ *****************************************************************************/
+const char *bcmbal_get_interface_type_str(bcmbal_intf_type int_type)
+{
+ const char *type_str;
+
+ switch (int_type)
+ {
+ case(BCMBAL_INTF_TYPE_PON):
+ {
+ type_str = "pon";
+ }
+ break;
+
+ case(BCMBAL_INTF_TYPE_NNI):
+ {
+ type_str = "nni";
+ }
+ break;
+
+ default:
+ {
+ type_str = "INVALID";
+ }
+ break;
+
+ }
+
+ return type_str;
+}
+
+
+/*@}*/
diff --git a/bal_release/src/lib/libbalapi/bal_api.dox b/bal_release/src/lib/libbalapi/bal_api.dox
new file mode 100644
index 0000000..f8db011
--- /dev/null
+++ b/bal_release/src/lib/libbalapi/bal_api.dox
@@ -0,0 +1,108 @@
+/*
+ * BAL Programmers Guide - introduction
+ */
+
+/** \mainpage BAL Public Interface Concept
+
+\section intro Introduction
+This document describes the BAL user interface. The user interface is constructed from a
+small set of public APIs and an objects model.
+
+The objects model is designed to manage different entities in the system, and enables a simple and intuitive
+approach for managing line card.
+
+The API layer is designed to enable the management of line card containing muultiple MAC and SWITCH devices
+and support any host application architecture. It includes a set of APIs to access the line card configuration and
+asynchronous indications to send events to the host application.
+
+The API layer is part of the Broadcom® BAL SDK, which is provided as C source code, which is
+independent of the CPU and operating system being used.
+
+\section object_model_table BAL Object Model
+
+The system is modeled as a set of managed objects. The term “object” here doesn’t imply any inheritance, it
+means an entity that can be addressed individually and has a set of properties (attributes) and methods
+(operations), for example, access_terminal, flow, etc.
+
+Each object can have multiple properties (aka attributes), whereas a property is an object parameter that can be set or
+retrieved independently.
+ - A property is a simple type or a structure containing one or more fields, where fields can themselves be
+structures
+ - Each property has a specific permission type, such as Read-Only (RO) and Read-Write (RW).
+
+Object properties are grouped into sections/management groups. The following sections can contain zero or
+more properties:
+ - Key—Field(s) that uniquely identify the object instance (for example, subscriber_terminal key = {subs_id, intf_id}).
+ - Configuration
+ - Read-Write, Read-Only and Write-Only configuration properties
+ - Statistics
+ - Performance monitoring counters
+ - Debug counters
+ - Autonomous Indications
+ - Notifications that are generated asynchronously.
+ Indications can be either autonomous (such as alarms) or asynchronous responses to previously
+ submitted configuration change (for instance, subscriber_terminal admin_state=up request).
+
+\section object_model_prop Object and Properties Implementation
+
+\subsection object_model_structs Object Structures
+
+The main input parameter of all the APIs is an object structure, referred to as the Object Request Message. Each
+object section has a different structure that includes a generic header, object key, and a specific section structure
+according to the section type (for example, configuration, statics, etc).
+ - Generic header: A basic component of all the different section structures is the object generic header
+ \ref bcmbal_obj
+
+ - The configuration structure bcmbal_xx_cfg contains:
+ - The generic header \ref bcmbal_cfg
+ - The object key, if any
+ - The structure bcmbal_xx_cfg_data, containing all object configuration properties
+
+ - This statistics structure bcmbal_xx_stat contains:
+ - The generic header \ref bcmbal_stat
+ - The object key, if any
+ - The structure bcmbal_xx_stat_data, containing all the object statistics
+
+ - The per-autonomous indication structure bcmbal_xx_auto_yy contains:
+ - The generic header \ref bcmbal_auto
+ - The autonomous message ID is stored in the subgroup field.
+ - The object key, if any
+ - The structure bcmbal_xx_auto_yy_data, containing all indication properties, if any
+
+\subsection object_model_init_macros Structure Initialization Macros
+The following macros are used for initializing objects:
+ - \ref BCMBAL_CFG_INIT(cfg_msg, _object, _key)
+ - \ref BCMBAL_STAT_INIT(stat_msg, _object, _key)
+
+The macros perform the following tasks:
+ - Check that the structure matches the object section.
+ - Clear all control fields in the generic header \ref bcmbal_obj.
+
+\subsection object_model_prop_macros Property Presence Mask Manipulation Macros
+The presence mask indicates which of the properties in the object structure need to be accessed (set/get, etc.)
+The mask is a bit field, wherein each bit corresponds to a specific property. The following macros should be used
+for setting the presence mask:
+
+ - Set configuration parameter value:\n
+ \ref BCMBAL_CFG_PROP_SET(_msg, _object, _parm_name, _parm_value)
+ - Indicate that the property should be fetched by a bcmolt_cfg_get() request:\n
+ \ref BCMBAL_CFG_PROP_GET(_msg, _object, _parm_name)
+ - Indicate that the statistic should be fetched by a bcmolt_stat_get() request:\n
+ \ref BCMBAL_STAT_PROP_GET(_msg, _object, _parm_name)
+
+\subsection object_model_enums Enumerations
+In the following descriptions, XX is the object name and YY is the property name from the XML model.
+
+The system model includes the enumerations:
+ - The bcmbal_obj_id enumeration lists all objects. It includes per-object BCMBAL_OBJ_ID_XX constants,
+ where XX is the object name from the XML model.
+ - The bcmbal_xx_cfg_id enumeration lists all XX objects' properties from the “Configuration” section in the
+ XML model. It includes the BCMBAL_XX_CFG_ID_YY constants.
+ - The bcmbal_xx_stat_id enumeration lists all XX object's properties from the “Statistics” section in the XML
+ model. It includes the BCMBAL_XX_STAT_ID_YY constants.
+ - The bcmbal_xx_auto_id enumeration lists all XX object's indications from the “Autonomous Indications”
+ section in the XML model. It includes the BCMBAL_XX_AUTO_ID_YY constants.
+
+\section api_section BAL Public API
+ See \ref api in API Reference chapter
+*/
diff --git a/bal_release/src/lib/libbalapi/bal_api.h b/bal_release/src/lib/libbalapi/bal_api.h
new file mode 100644
index 0000000..60f1e0b
--- /dev/null
+++ b/bal_release/src/lib/libbalapi/bal_api.h
@@ -0,0 +1,286 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_api.h
+ * @brief Function declarations and all inclusions required for the BAL Public API
+ *
+ * @defgroup api BAL Public API
+ */
+#ifndef BCMBAL_API_H
+#define BCMBAL_API_H
+
+#include <bcmos_system.h>
+#include <bcmolt_model_types.h>
+
+#include <bal_objs.h>
+
+
+/*@{*/
+
+/*
+ * This example only controls the default access terminal
+ */
+#define DEFAULT_ATERM_ID (0)
+
+/* Max number of access-terminals supported by BAL */
+#define MAX_ACC_TERM_ID (255)
+
+/*------------------------------------------------
+ * See the bal_objs.h file for the BAL objects
+ *------------------------------------------------
+ */
+
+/*
+ * An enumeration of the BAL mgmt operations
+ */
+typedef enum
+{
+ BCMBAL_MGMT_OPER_ID_SET = 1 << 0,
+ BCMBAL_MGMT_OPER_ID_GET = 1 << 1,
+ BCMBAL_MGMT_OPER_ID_GET_STATS = 1 << 2,
+ BCMBAL_MGMT_OPER_ID_CLEAR = 1 << 3,
+ BCMBAL_MGMT_OPER_ID__NUM_OF = 1 << 4,
+ BCMBAL_MGMT_OPER_ID_ALL = BCMBAL_MGMT_OPER_ID__NUM_OF - 1,
+} bcmbal_mgmt_oper_id;
+
+
+/* access_terminal:key:acc_term_id max value */
+#define BAL_API_MAX_ACC_TERM_ID (255)
+
+/* flow:key:flow_id max value */
+#define BAL_API_MAX_FLOW_ID (65535)
+
+/* interface:mtu limits */
+#define BAL_API_MIN_INTF_MTU_SIZE (64)
+#define BAL_API_MAX_INTF_MTU_SIZE (9216)
+
+/* Max number of interfaces per interface:type in BAL */
+#define BAL_API_MAX_INTF_ID (15)
+
+/* Max sub_term_id per interface for the various modes */
+#define BAL_API_MAX_SUB_TERM_ID_GPON (127)
+#define BAL_API_MAX_SUB_TERM_ID_EPON (256)
+#define BAL_API_MAX_SUB_TERM_ID_XGPON (511)
+
+/* Max and min values for interface attributes */
+#define BAL_API_MIN_LOW_DATA_AGG_PORT_ID (256)
+#define BAL_API_MAX_LOW_DATA_AGG_PORT_ID (14591)
+
+#define BAL_API_MIN_LOW_DATA_SVC_PORT_ID (1024)
+#define BAL_API_MAX_LOW_DATA_SVC_PORT_ID (57598)
+
+
+/* Max and Min values for agg_port_id and svc_port_id */
+#define BAL_API_MIN_DATA_SVC_PORT_ID (256)
+#define BAL_API_MAX_DATA_SVC_PORT_ID (16383)
+
+/* Max and Min values for agg_port_id and svc_port_id */
+#define BAL_API_MIN_DATA_AGG_PORT_ID (256)
+#define BAL_API_MAX_DATA_AGG_PORT_ID (16383)
+
+/* Max value for pbits */
+#define MAX_PBITS_VALUE (7)
+
+/*
+ * BAL CLI max values
+ */
+/** Max number of supported OLTs */
+#define MAX_SUPPORTED_OLTS (BAL_API_MAX_ACC_TERM_ID+1)
+
+/** Max number of supported subscriber terminals (ONUs) */
+#define MAX_SUPPORTED_SUBS (BAL_API_MAX_SUB_TERM_ID_XGPON+1)
+
+/** Max number of supported flows */
+#define MAX_SUPPORTED_FLOWS (BAL_API_MAX_FLOW_ID+1)
+
+/** Max number of supported PON and NNI interfaces */
+#define MAX_SUPPORTED_INTF (BAL_API_MAX_INTF_ID+1)
+
+/** BAL Indication callback handler function prototype */
+typedef void (*f_bcmbal_ind_handler)(bcmbal_obj *obj);
+
+/** BAL Indication callback registration parameters */
+typedef struct bcmbal_cb_cfg
+{
+ bcmbal_obj_id obj_type; /**< Object type */
+ f_bcmbal_ind_handler ind_cb_hdlr; /**< Indication callback function. NULL=unregister */
+ bcmos_module_id module; /**< Target module id.
+ If it is BCMOS_MODULE_ID_NONE (0), the callback will be called
+ in BAL's context. Otherwise, it will be called in application
+ module's context */
+} bcmbal_cb_cfg; /* This structure is used for passing the mgmt queue
+
+ * IP:port information between the core main thread and
+ * core worker thread and bal API.
+ */
+typedef struct mgmt_queue_addr_ports
+{
+ const char *core_mgmt_ip_port;
+ const char *balapi_mgmt_ip_port;
+} mgmt_queue_addr_ports;
+
+extern dev_log_id log_id_public_api;
+
+const char *bcmbal_get_interface_type_str(bcmbal_intf_type int_type);
+
+/*
+ *------------------------------------------------------------------------------------------
+ *
+ * @brief The BAL Public API
+ *
+ *------------------------------------------------------------------------------------------
+ */
+
+/**
+ * @brief Initialize the BAL Public API internal data structures
+ *
+ * @param balapi_mgmt_ip_port The IP:port of the BAL API management queue
+ *
+ * @param core_mgmt_ip_port The IP:port of the core management queue
+ *
+ * @returns bcmos_errno
+ *
+ **/
+bcmos_errno bcmbal_api_init(const char *balapi_mgmt_ip_port, const char *core_mgmt_ip_port);
+
+/**
+ * @brief Un-initialize the BAL Public API internal data structures
+ *
+ * @returns bcmos_errno == BCM_ERR_OK
+ *
+ **/
+bcmos_errno bcmbal_api_finish(void);
+
+/**
+ * @brief BAL Public API Set (or modify) command.
+ *
+ * Set (or modify) the specified object instance (with implicit creation
+ * of dynamic objects) associated with the specified access-terminal device.
+ *
+ * @param objinfo A pointer to a BAL object
+ *
+ * @returns bcmos_errno
+ *
+ **/
+bcmos_errno bcmbal_cfg_set(bcmbal_cfg *objinfo);
+
+/**
+ * @brief BAL Public API Get command.
+ *
+ * Get the specified object instance
+ *
+ * @param objinfo A pointer to a BAL object
+ *
+ * @returns bcmos_errno
+ *
+ */
+bcmos_errno bcmbal_cfg_get(bcmbal_cfg *objinfo);
+
+/**
+ * @brief BAL Public API Packet Send function.
+ *
+ * Send a packet to the specified destination
+ *
+ * @param dest The destination of the user packet
+ *
+ * @param packet_to_send A pointer to the user packet to send to the specified destination
+ *
+ * @param packet_len The length of the user packet (must be <=1600 bytes)
+ *
+ * @returns bcmos_errno
+ *
+ */
+bcmos_errno bcmbal_pkt_send(bcmbal_dest dest,
+ const char *packet_to_send,
+ uint16_t packet_len);
+
+/**
+ * @brief BAL Public API Clear command.
+ *
+ * Set all attributes to default (or remove the object instance for
+ * dynamic objects) for the specified object instance
+ *
+ * @param objinfo A pointer to a BAL object
+ *
+ * @returns bcmos_errno
+ *
+ */
+bcmos_errno bcmbal_cfg_clear(bcmbal_cfg * objinfo);
+
+/**
+ * @brief BAL Public API Get Stats command.
+ *
+ * Get (and clear) the stats associated with specified object instance
+ *
+ * @param objinfo A pointer to a BAL object
+ *
+ * @returns bcmos_errno
+ *
+ */
+bcmos_errno bcmbal_stat_get(bcmbal_stat *objinfo);
+
+/**
+ * @brief BAL Public API indication subscription.
+ *
+ * Subscription function for the specified indications
+ *
+ * @param cb_cfg A pointer to the callback configuration parameters for the
+ * object indications being subscribed to.
+ *
+ * @returns bcmos_errno
+ *
+ */
+bcmos_errno bcmbal_subscribe_ind(bcmbal_cb_cfg *cb_cfg);
+
+/**
+ * @brief BAL Public API indication un-subscription.
+ *
+ * Un-subscription function for the specified (or all) indications
+ *
+ * @param cb_cfg A pointer to the callback configuration parameters for the
+ * object indications being un-subscribed from.
+ *
+ * @returns bcmos_errno
+ *
+ */
+bcmos_errno bcmbal_unsubscribe_ind(bcmbal_cb_cfg *cb_cfg);
+
+/**
+ * @brief Get the number of NNI ports supported by the running system
+ *
+ * @returns Number of NNI ports
+ */
+uint16_t bcmbal_num_nni_ports_get(void);
+
+/*@}*/
+
+#endif /* BCMBAL_API_H */
diff --git a/bal_release/src/lib/libbalapi/bal_api_worker.c b/bal_release/src/lib/libbalapi/bal_api_worker.c
new file mode 100644
index 0000000..178060c
--- /dev/null
+++ b/bal_release/src/lib/libbalapi/bal_api_worker.c
@@ -0,0 +1,513 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_api_worker.c
+ * @brief Main processing loop for the worker thread that handles INDications
+ * sent from the core to the BAL public API
+ *
+ */
+
+/*
+ * We need access to the BAL subsystem names
+ */
+#define BAL_SUBSYSTEM_STR_REQ
+
+#include <bcmos_system.h>
+#include <bal_msg.h>
+#include <bal_obj_msg_pack_unpack.h>
+#include <bal_osmsg.h>
+#include <bal_api.h>
+#include "bal_api_worker.h"
+#ifdef BAL_MONOLITHIC
+#include <bal_worker.h>
+#endif
+#ifdef ENABLE_LOG
+#include <bcm_dev_log.h>
+#endif
+
+/* This rx thread and worker thread are used to process indications from the core
+ */
+static bcmos_task api_ind_rx_thread;
+static bcmos_task api_ind_worker_thread;
+
+/* Local function declarations */
+static int _bal_ipc_api_ind_rx_handler(long data);
+static void bal_ipc_api_indication_handler(bcmos_module_id module_id, bcmos_msg *msg);
+
+
+typedef struct indication_subscription_inst indication_subscription_inst;
+struct indication_subscription_inst
+{
+ bcmbal_cb_cfg cb_cfg;
+ /**< TAILQ link for list management */
+ TAILQ_ENTRY(indication_subscription_inst) indication_subscription_inst_next;
+};
+
+TAILQ_HEAD(indication_subscription_list_head, indication_subscription_inst) indication_subscription_list;
+
+/*
+ * The queue through which the core converses with
+ * the backend of the Public API for indications.
+ */
+static bcmos_msg_queue bal_api_ind_backend_queue;
+bcmos_msg_queue *p_bal_api_ind_queue;
+
+/* Create API backend message queue */
+bcmos_errno bal_api_ind_msg_queue_create(mgmt_queue_addr_ports *mgmt_queue_info)
+{
+ bcmos_msg_queue_parm msg_q_p = {};
+ bcmos_errno ret = BCM_ERR_OK;
+
+ do
+ {
+ /* Create BAL API indication receive queue - the core sends IND messages
+ * to the BAL public API using this queue.
+ */
+ msg_q_p.name = "api_ind_rx_q";
+
+ if (NULL != mgmt_queue_info->balapi_mgmt_ip_port)
+ {
+ uint16_t portnum;
+ char *p_ind_portnum_str;
+ char balapi_ind_port_str[256];
+
+ /*
+ * make a copy of the user chosen bal api mgmt port
+ */
+ strcpy(balapi_ind_port_str, mgmt_queue_info->balapi_mgmt_ip_port);
+
+ /* Find the port number */
+ p_ind_portnum_str = strchr(balapi_ind_port_str, ':') + 1;
+
+ /* convert to an integer and increment it by one */
+ portnum = atoi(p_ind_portnum_str) + 1;
+
+ /* create the new string defining the BAL API indication port */
+ sprintf(p_ind_portnum_str,"%d", portnum);
+
+ /* Set up the BAL API indication IP:port access parameter
+ */
+ msg_q_p.local_ep_address = balapi_ind_port_str;
+ msg_q_p.remote_ep_address = NULL;
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_UDP_SOCKET;
+ }
+ else
+ {
+ msg_q_p.ep_type = BCMOS_MSG_QUEUE_EP_LOCAL;
+ }
+
+ ret = bcmos_msg_queue_create(&bal_api_ind_backend_queue, &msg_q_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't BAL API rx indication queue\n");
+ break;
+ }
+
+ p_bal_api_ind_queue = &bal_api_ind_backend_queue;
+#ifdef BAL_MONOLITHIC
+ if (NULL == mgmt_queue_info->balapi_mgmt_ip_port)
+ p_bal_core_to_api_ind_queue = p_bal_api_ind_queue;
+#endif
+ } while (0);
+
+ return ret;
+}
+
+/* Worker module init function.
+ * Register for messages this module is expected to receive
+ */
+static bcmos_errno _bal_worker_module_bal_api_init(long data)
+{
+ bcmos_task_parm task_p = {};
+ bcmos_errno ret = BCM_ERR_OK;
+
+ BUG_ON(0 == data);
+
+ do
+ {
+ /* Create BAL API indication RX thread */
+ task_p.name = "ipc_api_ind_rx_thread";
+ task_p.priority = TASK_PRIORITY_IPC_RX;
+ task_p.handler = _bal_ipc_api_ind_rx_handler;
+ task_p.data = (long)&bal_api_ind_backend_queue;
+
+ ret = bcmos_task_create(&api_ind_rx_thread, &task_p);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API indication RX thread\n");
+ break;
+ }
+
+ /* Register the message types to be handled by the mgmt module
+ */
+ bcmos_msg_register(BCMBAL_MGMT_API_IND_MSG,
+ 0,
+ BCMOS_MODULE_ID_WORKER_API_IND, bal_ipc_api_indication_handler);
+
+ }
+ while(0);
+
+ return ret;
+}
+
+static int _bal_ipc_api_ind_rx_handler(long data)
+{
+ bcmos_msg_queue *rxq = (bcmos_msg_queue *)data;
+ bcmos_task *my_task = bcmos_task_current();
+ bcmos_msg *msg;
+ bcmos_errno ret = BCM_ERR_OK;
+ void *payload;
+
+ while (!my_task->destroy_request)
+ {
+ payload = NULL;
+ ret = bcmbal_msg_recv(rxq, BCMOS_WAIT_FOREVER, &payload);
+ if (ret)
+ {
+ /* Unexpected failure */
+ BCM_LOG(ERROR, log_id_public_api, "bcmbal_msg_recv() -> %s\n", bcmos_strerror(ret));
+ continue;
+ }
+
+ /* Message received */
+ BCM_LOG(DEBUG, log_id_public_api, "bcmbal_msg_recv(%p) -> %s\n", payload, bcmos_strerror(ret));
+
+ /*
+ * Got a message, so now dispatch it. This will result in one
+ * of the modules (registered for the message being processed)
+ * executing its message callback handler.
+ */
+ msg = bcmbal_bcmos_hdr_get(payload);
+ ret = bcmos_msg_dispatch(msg, BCMOS_MSG_SEND_AUTO_FREE);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "Couldn't dispatch message %d:%d\n",
+ (int)msg->type, (int)msg->instance);
+ }
+ }
+
+ my_task->destroyed = BCMOS_TRUE;
+
+ return (BCM_ERR_OK == ret) ? 0 : -EINVAL;
+}
+
+
+/* Message wrapper that is called when indication is delivered in application module's context */
+static void _int_deliver_wrapper_cb(bcmos_module_id module_id, bcmos_msg *msg)
+{
+ void *msg_payload = bcmbal_payload_ptr_get(bcmbal_bal_hdr_get_by_bcmos_hdr(msg));
+ f_bcmbal_ind_handler handler = (f_bcmbal_ind_handler)bcmbal_scratchpad_get(msg_payload);
+
+ handler((bcmbal_obj *)msg_payload);
+ bcmbal_msg_free((bcmbal_obj *)msg_payload);
+}
+
+static void process_listener_callbacks(bcmbal_obj *obj)
+{
+
+ indication_subscription_inst *current_entry, *p_temp_entry;
+
+ BCM_LOG(DEBUG, log_id_public_api, "inspecting registered callback for object %d\n",
+ obj->obj_type);
+
+ TAILQ_FOREACH_SAFE(current_entry,
+ &indication_subscription_list,
+ indication_subscription_inst_next,
+ p_temp_entry)
+ {
+ BCM_LOG(DEBUG, log_id_public_api, "entry objtype %d\n", current_entry->cb_cfg.obj_type);
+
+ if((BCMBAL_OBJ_ID_ANY == current_entry->cb_cfg.obj_type) ||
+ (current_entry->cb_cfg.obj_type == obj->obj_type))
+ {
+ BCM_LOG(DEBUG, log_id_public_api,
+ "Calling registered callback for object %d\n",
+ obj->obj_type);
+
+ /* call the registered function directly or in the target module's context */
+ if (BCMOS_MODULE_ID_NONE == current_entry->cb_cfg.module)
+ {
+ current_entry->cb_cfg.ind_cb_hdlr(obj);
+ }
+ else
+ {
+ bcmbal_obj *clone = bcmbal_msg_clone(obj);
+ bcmos_errno err;
+ if (NULL == clone)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "Couldn't clone message for object %d\n",
+ obj->obj_type);
+ continue;
+ }
+ bcmbal_scratchpad_set(clone, current_entry->cb_cfg.ind_cb_hdlr);
+ err = bcmbal_msg_call(clone,
+ current_entry->cb_cfg.module,
+ _int_deliver_wrapper_cb,
+ BCMOS_MSG_SEND_AUTO_FREE);
+ if (BCM_ERR_OK != err)
+ {
+ BCM_LOG(ERROR, log_id_public_api,
+ "Couldn't deliver message for object %d to module %d. Error %s\n",
+ obj->obj_type, current_entry->cb_cfg.module, bcmos_strerror(err));
+ }
+ }
+ }
+ }
+
+ return;
+}
+
+/*
+ * This is the handler for indication messages received by the BAL Public API
+ * backend from the core. We need to see who has subscribed for these messages,
+ * and call those registered functions.
+ */
+static void bal_ipc_api_indication_handler(bcmos_module_id module_id, bcmos_msg *msg)
+{
+
+ void *msg_payload;
+
+ msg_payload = bcmbal_payload_ptr_get(bcmbal_bal_hdr_get_by_bcmos_hdr(msg));
+
+ /*
+ * TO-DO
+ * validate the message major and minor version is correct
+ */
+
+ do
+ {
+ if(BAL_SUBSYSTEM_CORE != bcmbal_sender_get(msg_payload))
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Mgmt IND message received from wrong subsystem (%s)\n",
+ subsystem_str[bcmbal_sender_get(msg_payload)]);
+ break;
+ }
+
+ if(BCMBAL_MGMT_API_IND_MSG != bcmbal_type_major_get(msg_payload))
+ {
+ BCM_LOG(ERROR, log_id_public_api,"Mgmt IND message received with wrong major type (%d)\n",
+ bcmbal_type_major_get(msg_payload));
+ break;
+ }
+
+ /* Look through the list of registered subscribers for this indication
+ * and call them.
+ */
+ BCM_LOG(DEBUG, log_id_public_api,
+ "Processing indication listeners\n");
+
+ process_listener_callbacks((bcmbal_obj *)msg_payload);
+
+ }
+ while(0);
+
+ bcmbal_msg_free(msg_payload);
+
+ return;
+}
+
+void enable_bal_api_indications(const char *balapi_mgmt_ip_port)
+{
+
+ bcmos_task_parm task_p = {};
+ bcmos_module_parm module_p = {};
+ bcmos_errno ret = BCM_ERR_OK;
+ mgmt_queue_addr_ports mgmt_queue_info;
+
+ TAILQ_INIT(&indication_subscription_list);
+
+ do
+ {
+ /* Create quues for communication between BAL API and the core */
+ mgmt_queue_info.balapi_mgmt_ip_port = balapi_mgmt_ip_port;
+ ret = bal_api_ind_msg_queue_create(&mgmt_queue_info);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API indication queue\n");
+ break;
+ }
+
+ module_p.qparm.name = "bal_api_ind_worker_module";
+ module_p.init = _bal_worker_module_bal_api_init;
+ module_p.data = (long)&mgmt_queue_info; /* IP address and port information */
+
+ /* Create worker thread & modules for BAL indication messages from the core */
+ task_p.name = "bal_api_ind_worker";
+ task_p.priority = TASK_PRIORITY_WORKER;
+
+ ret = bcmos_task_create(&api_ind_worker_thread, &task_p);
+ if (BCM_ERR_OK != ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API indication worker thread\n");
+ break;
+ }
+
+ ret = bcmos_module_create(BCMOS_MODULE_ID_WORKER_API_IND, &api_ind_worker_thread, &module_p);
+ if (ret)
+ {
+ BCM_LOG(ERROR, log_id_public_api, "Couldn't create BAL API indication worker module\n");
+ break;
+ }
+
+ BCM_LOG(DEBUG, log_id_public_api, "BAL API indication handler registered\n");
+
+ }
+ while(0);
+
+ return;
+}
+
+
+/** NOTE: when cb_cfg->obj_type is BCMBAL_OBJ_ID_ANY AND type is UN-SUBSCRIBE, then this is unsubscribe all */
+bcmos_errno _manage_api_ind_listener(bcmbal_ind_cb_management_type type, bcmbal_cb_cfg *cb_cfg)
+{
+
+ bcmos_errno ret = BCM_ERR_OK;
+ indication_subscription_inst *new_ind_entry;
+ indication_subscription_inst *current_entry, *p_temp_entry;
+ bcmos_bool is_unsubscribe;
+
+ BUG_ON(NULL == cb_cfg);
+ BUG_ON(NULL == cb_cfg->ind_cb_hdlr);
+
+ is_unsubscribe = (IND_CB_UNSUBSCRIBE == type);
+
+ BCM_LOG(DEBUG,log_id_public_api,
+ "%s: %s for BAL API indications\n",
+ __FUNCTION__,
+ is_unsubscribe ? "Unsubscribing" : "Subscribing");
+
+ do
+ {
+ bcmos_bool b_found_existing_entry = BCMOS_FALSE;
+
+ TAILQ_FOREACH_SAFE(current_entry,
+ &indication_subscription_list,
+ indication_subscription_inst_next,
+ p_temp_entry)
+ {
+ if(
+ ((is_unsubscribe && (BCMBAL_OBJ_ID_ANY == cb_cfg->obj_type)) ? BCMOS_TRUE :
+ (current_entry->cb_cfg.obj_type == cb_cfg->obj_type)) &&
+ (current_entry->cb_cfg.ind_cb_hdlr == cb_cfg->ind_cb_hdlr) &&
+ (current_entry->cb_cfg.module == cb_cfg->module))
+ {
+ BCM_LOG(DEBUG,log_id_public_api,
+ "Found existing registration\n");
+
+ if(is_unsubscribe)
+ {
+ BCM_LOG(DEBUG,log_id_public_api,
+ "Removing registration\n");
+ TAILQ_REMOVE(&indication_subscription_list, current_entry, indication_subscription_inst_next);
+ bcmos_free(current_entry);
+ }
+
+ b_found_existing_entry = BCMOS_TRUE;
+
+ /* Don't stop looking for matches if we are unsubscribing from ANY indications, there could be many
+ * assigned to a single callback function */
+ if(!(is_unsubscribe && (BCMBAL_OBJ_ID_ANY == cb_cfg->obj_type))) break;
+ }
+
+ }
+
+ /* If we are subscribing to indication and we have already recorded
+ * this subscription, OR we are un-subscribing (whether or not we
+ * found a subscription to remove), then return right away with OK
+ */
+ if((BCMOS_TRUE == b_found_existing_entry) || is_unsubscribe)
+ {
+ break;
+ }
+
+ BCM_LOG(DEBUG,log_id_public_api,
+ "Registering NEW subscriber for BAL API indications\n");
+
+ /* This is a new subscription */
+ new_ind_entry = bcmos_calloc(sizeof(indication_subscription_inst));
+
+ if (NULL == new_ind_entry)
+ {
+ BCM_LOG(FATAL, log_id_public_api,
+ "Failed to register api indication subscription\n");
+ ret = BCM_ERR_NOMEM;
+ break;
+ }
+
+ new_ind_entry->cb_cfg = *cb_cfg;
+
+ TAILQ_INSERT_TAIL(&indication_subscription_list, new_ind_entry, indication_subscription_inst_next);
+
+ } while(0);
+
+ return ret;
+
+}
+
+static void free_all_indication_subscriptions(void)
+{
+ indication_subscription_inst *current_entry, *p_temp_entry;
+
+ TAILQ_FOREACH_SAFE(current_entry,
+ &indication_subscription_list,
+ indication_subscription_inst_next,
+ p_temp_entry)
+ {
+ TAILQ_REMOVE(&indication_subscription_list, current_entry, indication_subscription_inst_next);
+ bcmos_free(current_entry);
+ }
+
+ return;
+}
+
+
+void bal_api_indications_finish(void)
+{
+ free_all_indication_subscriptions();
+
+ bcmos_msg_unregister(BCMBAL_MGMT_API_IND_MSG,
+ 0,
+ BCMOS_MODULE_ID_WORKER_API_IND);
+
+ bcmos_msg_queue_destroy(&bal_api_ind_backend_queue);
+
+ bcmos_module_destroy(BCMOS_MODULE_ID_WORKER_API_IND);
+
+ bcmos_task_destroy(&api_ind_rx_thread);
+
+ bcmos_task_destroy(&api_ind_worker_thread);
+
+ return;
+}
diff --git a/bal_release/src/lib/libbalapi/bal_api_worker.h b/bal_release/src/lib/libbalapi/bal_api_worker.h
new file mode 100644
index 0000000..7e258ca
--- /dev/null
+++ b/bal_release/src/lib/libbalapi/bal_api_worker.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_worker.h
+ *
+ * @brief Bal worker thread included
+ *
+ * Module contains the data structures and functions used to support the
+ * BAL core worker thread.
+ */
+
+#ifndef BAL_API_WORKER_H
+#define BAL_API_WORKER_H
+
+#include <bcmos_errno.h>
+
+extern bcmos_msg_queue *p_balapi_to_core_queue;
+
+typedef enum {
+ IND_CB_SUBSCRIBE,
+ IND_CB_UNSUBSCRIBE
+}bcmbal_ind_cb_management_type;
+
+/*
+ * Function declarations
+ */
+extern bcmos_errno bal_api_ind_msg_queue_create(mgmt_queue_addr_ports *mgmt_queue_info);
+extern void enable_bal_api_indications(const char *balapi_mgmt_ip_port);
+extern bcmos_errno _manage_api_ind_listener(bcmbal_ind_cb_management_type type, bcmbal_cb_cfg *cb_cfg);
+extern void bal_api_indications_finish(void);
+
+
+#endif /* BAL_API_WORKER_H */
diff --git a/bal_release/src/lib/libbalapicli/Makefile b/bal_release/src/lib/libbalapicli/Makefile
new file mode 100644
index 0000000..44b7bac
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/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 = bal_api_cli
+MOD_TYPE = lib
+MOD_DEPS = cli bal_api
+MOD_INC_DIRS = $(SRC_DIR) $(OUT_DIR)
+
+srcs = bal_api_cli.c bal_api_cli_dump.c
+gen_bal_srcs = bal_api_cli_helpers.c bal_api_cli_handlers.c
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli.c b/bal_release/src/lib/libbalapicli/bal_api_cli.c
new file mode 100644
index 0000000..cbbe973
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli.c
@@ -0,0 +1,1059 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(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 <bcmos_system.h>
+#include <bcmcli.h>
+#include <bal_api.h>
+#include "bal_api_cli.h"
+#include "bal_api_cli_helpers.h"
+#include "bal_api_cli_handlers.h"
+
+#define BCMBAL_APICLI_CAST_DISCARD_CONST(p, type) (type)((long)(p))
+
+/* bool enum table */
+static bcmcli_enum_val bool_enum[] =
+{
+ { .name = "yes", .val = 1 },
+ { .name = "no", .val = 0 },
+ BCMCLI_ENUM_LAST
+};
+
+static bcmbal_apicli_type_descr bool_type_descr = {
+ .name = "bool",
+ .descr = "Boolean",
+ .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM,
+ .size = sizeof(bcmos_bool),
+ .x = {.e = bool_enum}
+};
+
+/* parameter data */
+typedef struct
+{
+ const bcmbal_apicli_prop_descr *prop; /* property */
+ const bcmbal_apicli_field_descr *field; /* field or NULL */
+ const bcmbal_apicli_field_descr *array_fd; /* array field descriptor or NULL */
+ uint16_t offset; /* offset from the beginning of the property */
+ uint16_t array_fd_offset; /* offset of array_fd from the beginning of the property */
+ bcmbal_mgt_group group; /* management group */
+} bcmbal_apicli_parm_data;
+
+typedef enum
+{
+ BCMBAL_APICLI_FLAGS_NONE = 0,
+ BCMBAL_APICLI_FLAGS_IGNORE_FIELDS = 1 << 0
+} bcmbal_apicli_flags;
+
+/* Current session */
+static bcmcli_session *current_session;
+
+/*
+ * helpers
+ */
+
+/* calculate number of fields in type */
+static uint32_t bcmbal_apicli_get_num_fields_in_type(const bcmbal_apicli_type_descr *td)
+{
+ uint16_t f;
+ uint32_t nf = 0;
+
+
+ switch (td->base_type)
+ {
+ case BCMBAL_APICLI_BASE_TYPE_ID_STRUCT:
+ {
+ if (!td->x.s.num_fields)
+ return 0;
+ BUG_ON(!td->x.s.fields);
+ for (f = 0; f < td->x.s.num_fields; f++)
+ {
+ nf += bcmbal_apicli_get_num_fields_in_type(td->x.s.fields[f].type);
+ }
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_UNION:
+ {
+ /* Union. Count only common fields */
+ nf = td->x.u.num_common_fields;
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED:
+ {
+ nf = bcmbal_apicli_get_num_fields_in_type(td->x.arr_fixed.elem_type);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN:
+ {
+ nf = bcmbal_apicli_get_num_fields_in_type(td->x.arr_dyn.elem_type);
+ break;
+ }
+
+ default:
+ {
+ nf = 1;
+ break;
+ }
+ }
+
+ return nf;
+}
+
+/* calculate number of property fields for given object+group+subgroup+access. simple property=single field */
+static bcmos_errno bcmbal_apicli_get_num_fields_in_group(bcmbal_obj_id o, bcmbal_mgt_group group, uint16_t subgroup,
+ bcmbal_apicli_prop_access_id access_level, uint32_t *nfields)
+{
+ uint32_t nf = 0;
+ int i;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ for (i = 0; rc != BCM_ERR_RANGE; i++)
+ {
+ const bcmbal_apicli_prop_descr *pd;
+ rc = bcmbal_apicli_object_property(o, group, subgroup, i, &pd);
+ if (rc == BCM_ERR_OK && (pd->access & access_level))
+ {
+ /* Calculate number of fields if write access. Count only properties for read access */
+ if ((access_level & BCMBAL_APICLI_PROP_ACCESS_ID_W) != 0)
+ {
+ BUG_ON(!pd->type);
+ nf += bcmbal_apicli_get_num_fields_in_type(pd->type);
+ }
+ else
+ {
+ ++nf;
+ }
+ }
+ }
+ *nfields = nf;
+
+ return BCM_ERR_OK;
+}
+
+/*
+ * Command handlers
+ */
+
+static bcmos_errno bcmbal_apicli_objects_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ int rc;
+ bcmbal_obj_id o;
+ const char *name, *descr;
+
+ bcmcli_print(session, "System Object Types:\n");
+ bcmcli_print(session, "=======================================\n");
+ bcmcli_print(session, "Id Name Description\n");
+ bcmcli_print(session, "=======================================\n");
+ for (o = 0; o < BCMBAL_OBJ_ID__NUM_OF; o++)
+ {
+ rc = bcmbal_apicli_object_name(o, &name, &descr);
+ if (!rc)
+ bcmcli_print(session, "%.4d %-22s %s\n", o, name, descr);
+ }
+
+ return 0;
+}
+
+static bcmos_errno bcmbal_apicli_set_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ return bcmbal_apicli_call(BCMBAL_MGT_GROUP_CFG, BCMBAL_OBJ_MSG_TYPE_SET, session);
+}
+
+static bcmos_errno bcmbal_apicli_get_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ return bcmbal_apicli_call(BCMBAL_MGT_GROUP_CFG, BCMBAL_OBJ_MSG_TYPE_GET, session);
+}
+
+static bcmos_errno bcmbal_apicli_clear_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ return bcmbal_apicli_call(BCMBAL_MGT_GROUP_CFG, BCMBAL_OBJ_MSG_TYPE_CLEAR, session);
+}
+
+static bcmos_errno bcmbal_apicli_stat_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ return bcmbal_apicli_call(BCMBAL_MGT_GROUP_STAT, BCMBAL_OBJ_MSG_TYPE_GET, session);
+}
+
+/*
+ * Init-time helpers
+ */
+
+/* map to CLI type */
+static bcmos_errno bcmbal_apicli_map_type(
+ const bcmbal_apicli_type_descr *td,
+ const bcmbal_apicli_type_descr *array_td,
+ bcmcli_cmd_parm *cmd_parm)
+{
+ bcmbal_apicli_parm_data *parm_data = cmd_parm->user_data;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ /* Map type */
+ switch(td->base_type)
+ {
+ case BCMBAL_APICLI_BASE_TYPE_ID_SNUM:
+ cmd_parm->type = BCMCLI_PARM_NUMBER;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_UNUM:
+ cmd_parm->type = BCMCLI_PARM_UNUMBER;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX:
+ cmd_parm->type = BCMCLI_PARM_HEX;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_BOOL:
+ cmd_parm->type = BCMCLI_PARM_ENUM;
+ cmd_parm->enum_table = bool_enum;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_FLOAT:
+ cmd_parm->type = td->size == sizeof(double) ? BCMCLI_PARM_DOUBLE : BCMCLI_PARM_FLOAT;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_STRING:
+ cmd_parm->type = BCMCLI_PARM_STRING;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_IPV4:
+ cmd_parm->type = BCMCLI_PARM_IP;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_MAC:
+ cmd_parm->type = BCMCLI_PARM_MAC;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_ENUM:
+ cmd_parm->type = BCMCLI_PARM_ENUM;
+ cmd_parm->enum_table = td->x.e;
+ break;
+ case BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK:
+ cmd_parm->type = BCMCLI_PARM_ENUM_MASK;
+ cmd_parm->enum_table = td->x.e;
+ break;
+ default:
+ bcmcli_print(current_session, "*** can't map type %s (%d)\n", td->name, (int)td->base_type);
+ rc = BCM_ERR_NOT_SUPPORTED;
+ break;
+ }
+
+ /* Map uint8_t array to buffer if it is independent (not structure field) */
+ if (array_td &&
+ td->size == 1 &&
+ (td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM || td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX) &&
+ (parm_data->array_fd == parm_data->field || !parm_data->field))
+ {
+ cmd_parm->type = BCMCLI_PARM_BUFFER;
+ }
+
+ return rc;
+}
+
+/* allocate memory for name and description and copy to to parm */
+static bcmos_errno bcmbal_apicli_copy_parm_name(bcmcli_cmd_parm *parm, const char *name, const char *descr)
+{
+ parm->name = bcmos_alloc(strlen(name) + 1);
+ parm->description = bcmos_alloc(strlen(descr) + 1);
+ if ((parm->name == NULL) || (parm->description == NULL))
+ {
+ /* Successful allocation if any will be released by common cleanup
+ * along with the rest of dynamic parameter fields */
+ return BCM_ERR_NOMEM;
+ }
+ strcpy(BCMBAL_APICLI_CAST_DISCARD_CONST(parm->name, void *), name);
+ strcpy(BCMBAL_APICLI_CAST_DISCARD_CONST(parm->description, void *), descr);
+ return BCM_ERR_OK;
+}
+
+/* populate single parameter */
+static int bcmbal_apicli_populate_parm1(
+ const bcmbal_apicli_prop_descr *pd,
+ const bcmbal_apicli_field_descr *fd,
+ const bcmbal_apicli_type_descr *td,
+ const bcmbal_apicli_field_descr *array_fd,
+ uint32_t offset,
+ uint32_t array_fd_offset,
+ bcmcli_cmd_parm *cmd_parm,
+ uint32_t cmd_flags,
+ char *name,
+ char *help)
+{
+ bcmbal_apicli_parm_data *parm_data = cmd_parm->user_data;
+ int rc;
+
+ parm_data->prop = pd;
+ parm_data->field = fd;
+ parm_data->offset = offset;
+ parm_data->array_fd = array_fd;
+ parm_data->array_fd_offset = array_fd_offset;
+
+ rc = bcmbal_apicli_copy_parm_name(cmd_parm, name, help);
+ if (rc)
+ {
+ return rc;
+ }
+ cmd_parm->flags = cmd_flags;
+ if (td->min_val != td->max_val || td->min_val)
+ {
+ cmd_parm->flags |= BCMCLI_PARM_FLAG_RANGE;
+ cmd_parm->low_val = td->min_val;
+ cmd_parm->hi_val = td->max_val;
+ }
+ rc = bcmbal_apicli_map_type(td, array_fd ? array_fd->type : NULL, cmd_parm);
+ if (rc < 0)
+ {
+ return rc;
+ }
+
+ /* Arrays require more work.
+ * - Calculate size. Known for fixed arrays, hard-coded max for dynamic
+ * - Allocate either buffer or array of values based on CLI parameter type
+ * - Calculate offset from the beginning of array entry
+ */
+ if (array_fd)
+ {
+ uint32_t array_size;
+
+ if (array_fd->type->base_type == BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED)
+ {
+ array_size = array_fd->type->x.arr_fixed.size;
+ }
+ else
+ {
+ array_size = array_fd->type->x.arr_dyn.max_size;
+ }
+ if (!array_size)
+ {
+ bcmcli_print(current_session, "*** Error in %s array descriptor. Size is not set.\n", array_fd->name);
+ return BCM_ERR_INTERNAL;
+ }
+ if (cmd_parm->type == BCMCLI_PARM_BUFFER)
+ {
+ rc = bcmbal_buf_alloc(&cmd_parm->value.buffer, array_size);
+ if (rc)
+ {
+ return rc;
+ }
+ }
+ else
+ {
+ cmd_parm->values = bcmos_calloc(sizeof(bcmcli_parm_value) * array_size);
+ if (!cmd_parm->values)
+ {
+ return BCM_ERR_NOMEM;
+ }
+ cmd_parm->max_array_size = array_size;
+ }
+ }
+
+ return 1;
+}
+
+
+/* populate name buf and help buf */
+static void bcmbal_apicli_populate_name_help(const bcmbal_apicli_field_descr *fld, char *name_buf0, char *help_buf0,
+ char *name_buf, char *help_buf)
+{
+ name_buf[0] = 0;
+ help_buf[0] = 0;
+ bcmcli_strncpy(name_buf, name_buf0, BCMBAL_APICLI_MAX_PARM_NAME_LENGTH);
+ if (strlen(name_buf))
+ bcmcli_strncat(name_buf, ".", BCMBAL_APICLI_MAX_PARM_NAME_LENGTH);
+ bcmcli_strncat(name_buf, fld->cli_name ? fld->cli_name : fld->name, BCMBAL_APICLI_MAX_PARM_NAME_LENGTH);
+ bcmcli_strncpy(help_buf, help_buf0, BCMBAL_APICLI_MAX_PARM_HELP_LENGTH);
+ bcmcli_strncat(help_buf, " - ", BCMBAL_APICLI_MAX_PARM_HELP_LENGTH);
+ bcmcli_strncat(help_buf, fld->descr ? fld->descr : fld->name, BCMBAL_APICLI_MAX_PARM_HELP_LENGTH);
+}
+
+/* Allocate CLI parameter array. Set up parm->data */
+static bcmcli_cmd_parm *bcmbal_apicli_parm_alloc(int nparms)
+{
+ uint32_t size;
+ bcmcli_cmd_parm *parms;
+ bcmbal_apicli_parm_data *parm_data;
+ int i;
+
+ /* Allocate parameter table and populate it */
+ size = (sizeof(bcmcli_cmd_parm) + sizeof(bcmbal_apicli_parm_data)) * (nparms + 1);
+ parms = bcmos_calloc(size);
+ if (!parms)
+ return NULL;
+
+ /* Associate parameter_data structs with parameters */
+ parm_data = (bcmbal_apicli_parm_data *)(parms + nparms + 1);
+ for (i = 0; i < nparms; i++)
+ {
+ parms[i].user_data = &parm_data[i];
+ }
+ return parms;
+}
+
+/* clone enum table */
+static bcmcli_enum_val *bcmbal_apicli_clone_enum_table(bcmcli_cmd_parm *parm)
+{
+ bcmcli_enum_val *org_table = parm->enum_table;
+ bcmcli_enum_val *val = org_table;
+ bcmcli_enum_val *clone_table = org_table;
+ int i, n;
+
+ BUG_ON(parm->type != BCMCLI_PARM_ENUM);
+ while (val && val->name)
+ {
+ ++val;
+ }
+ n = val - org_table;
+
+ clone_table = bcmos_calloc(sizeof(bcmcli_enum_val) * (n + 1));
+ if (!clone_table)
+ {
+ return NULL;
+ }
+ for (i = 0; i < n; i++)
+ {
+ clone_table[i].name = org_table[i].name;
+ clone_table[i].val = org_table[i].val;
+ }
+ return clone_table;
+}
+
+
+/* populate CLI parameter(s) from a single property. Can be multiple parameters
+ * if property contains multiple fields.
+ * Returns number of parameters populated >= 0 or error < 0
+ */
+static int bcmbal_apicli_populate_parms_from_property(const bcmbal_apicli_prop_descr *pd,
+ const bcmbal_apicli_field_descr *fd, const bcmbal_apicli_field_descr *array_fd, uint32_t offset,
+ uint32_t array_fd_offset, bcmcli_cmd_parm *parms, bcmbal_apicli_prop_access_id access_level, uint32_t cmd_flags,
+ char *name_buf0, char *help_buf0)
+{
+ const bcmbal_apicli_type_descr *td = fd ? fd->type : pd->type;
+ uint32_t nf = 0;
+ char name_buf[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
+ char help_buf[BCMBAL_APICLI_MAX_PARM_HELP_LENGTH];
+ int rc = 0;
+
+ /* presence masks are not set directly, they are calculated based on other fields */
+ if (fd != NULL && (fd->flags & BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK) != 0)
+ {
+ return BCM_ERR_READ_ONLY;
+ }
+
+ /* At top level take name from property */
+ if (td == pd->type)
+ {
+ /* In case there's a global prefix */
+ char *top_name_buf = name_buf0;
+ uint32_t top_name_buf_len = BCMBAL_APICLI_MAX_PARM_NAME_LENGTH;
+ uint32_t prefix_len = strlen(name_buf0);
+ if (prefix_len > 0)
+ {
+ top_name_buf += prefix_len;
+ top_name_buf_len -= prefix_len;
+ }
+
+ bcmcli_strncpy(top_name_buf, pd->cli_name ? pd->cli_name : pd->name, top_name_buf_len);
+ bcmcli_strncpy(help_buf0, pd->descr ? pd->descr : pd->name, BCMBAL_APICLI_MAX_PARM_HELP_LENGTH);
+ }
+
+ /* For read access we only mark whether read property or not. It is not field-by-field operation */
+ if (access_level == BCMBAL_APICLI_PROP_ACCESS_ID_R)
+ {
+ td = &bool_type_descr;
+ }
+
+ /* In case of arrays we should
+ * - check that there is no array in array. It is not supported
+ * - store array type descriptor FFU and replace the "current" type descriptor with element type
+ * - reset offset because for array fields it should be calculated from array base rather than property
+ */
+ if (td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN || td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED)
+ {
+ if (array_fd)
+ {
+ bcmcli_print(
+ current_session,
+ "*** %s in %s: arrays-in-arrays are not supported\n",
+ pd->name,
+ array_fd->name);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ /* store array type and fetch element type */
+ array_fd = fd ? fd : (const bcmbal_apicli_field_descr *)pd;
+ if (td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN)
+ {
+ td = td->x.arr_dyn.elem_type;
+ }
+ else
+ {
+ td = td->x.arr_fixed.elem_type;
+ }
+ array_fd_offset = offset;
+ offset = 0;
+ }
+
+ if (td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_STRUCT)
+ {
+ uint16_t f;
+ if (!td->x.s.num_fields)
+ return 0;
+ BUG_ON(!td->x.s.fields);
+ for (f = 0; f < td->x.s.num_fields; f++)
+ {
+ const bcmbal_apicli_field_descr *fld = &td->x.s.fields[f];
+ bcmbal_apicli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
+ rc = bcmbal_apicli_populate_parms_from_property(pd, fld, array_fd, offset+fld->offset,
+ array_fd_offset, &parms[nf], access_level, cmd_flags, name_buf, help_buf);
+ if (rc > 0)
+ nf += rc;
+ }
+ }
+ else if (td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNION)
+ {
+ /* Union */
+ uint16_t f;
+ const bcmbal_apicli_field_descr *fld;
+ bcmcli_cmd_parm *sel_parm;
+ bcmbal_apicli_parm_data *sel_data;
+ bcmcli_enum_val *e;
+
+ if (!td->x.u.num_common_fields)
+ return 0;
+ BUG_ON(!td->x.u.common_fields);
+
+ /* Populate parameters preceding the union selector */
+ for (f = 0; f < td->x.u.classifier_idx; f++)
+ {
+ fld = &td->x.u.common_fields[f];
+ bcmbal_apicli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
+ rc = bcmbal_apicli_populate_parms_from_property(pd, fld, array_fd,
+ offset+fld->offset, array_fd_offset, &parms[nf], access_level, cmd_flags, name_buf, help_buf);
+ if (rc > 0)
+ nf += rc;
+ }
+
+ /* Now populate parameter for selector */
+ sel_parm = &parms[nf];
+ fld = &td->x.u.common_fields[f];
+ bcmbal_apicli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
+ rc = bcmbal_apicli_populate_parms_from_property(pd, fld, array_fd,
+ offset+fld->offset, array_fd_offset, sel_parm, access_level, cmd_flags, name_buf, help_buf);
+ if (rc > 0)
+ nf += rc;
+ /* Clone enum table in order to allow modifying it */
+ if (rc >= 1)
+ {
+ sel_parm->enum_table = bcmbal_apicli_clone_enum_table(sel_parm);
+ if (!sel_parm->enum_table)
+ {
+ rc = BCM_ERR_NOMEM;
+ }
+ }
+
+ /* Now set-up selector */
+ sel_parm->flags |= BCMCLI_PARM_FLAG_SELECTOR;
+ sel_data = sel_parm->user_data;
+ e = sel_parm->enum_table;
+ while (e && e->name && rc >= 0)
+ {
+ fld = &td->x.u.union_fields[e - sel_parm->enum_table];
+ if (fld->type)
+ {
+ int np = bcmbal_apicli_get_num_fields_in_type(fld->type);
+ int i;
+
+ e->parms = bcmbal_apicli_parm_alloc(np);
+ if (!e->parms)
+ {
+ rc = BCM_ERR_NOMEM;
+ break;
+ }
+ for (i = 0; i < np; i++)
+ {
+ bcmbal_apicli_parm_data *data = e->parms[i].user_data;
+ data->group = sel_data->group;
+ }
+ /* Collapse substructure name */
+ if (fld->type->base_type == BCMBAL_APICLI_BASE_TYPE_ID_STRUCT ||
+ fld->type->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNION)
+ {
+ bcmcli_strncpy(name_buf, name_buf0, sizeof(name_buf));
+ bcmcli_strncpy(help_buf, help_buf0, sizeof(help_buf));
+ }
+ else
+ {
+ bcmbal_apicli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
+ }
+ rc = bcmbal_apicli_populate_parms_from_property(pd, fld, array_fd,
+ offset+fld->offset, array_fd_offset, e->parms, access_level, cmd_flags, name_buf, help_buf);
+ }
+ ++e;
+ }
+
+ /* Finally populate parameters following the selector parameter */
+ for (f = td->x.u.classifier_idx + 1; f < td->x.u.num_common_fields && rc >= 0; f++)
+ {
+ fld = &td->x.u.common_fields[f];
+ bcmbal_apicli_populate_name_help(fld, name_buf0, help_buf0, name_buf, help_buf);
+ rc = bcmbal_apicli_populate_parms_from_property(pd, fld, array_fd,
+ offset+fld->offset, array_fd_offset, &parms[nf], access_level, cmd_flags, name_buf, help_buf);
+ if (rc > 0)
+ nf += rc;
+ }
+ }
+ else
+ {
+ /* Finally! Simple type that maps to a single CLI parameter */
+ nf = bcmbal_apicli_populate_parm1(pd, fd, td, array_fd, offset, array_fd_offset,
+ &parms[0], cmd_flags, name_buf0, help_buf0);
+ }
+ return (rc >= 0) ? nf : rc;
+}
+
+/* populate CLI parameter table */
+static int bcmbal_apicli_populate_parms(
+ bcmbal_obj_id o,
+ bcmbal_mgt_group group,
+ uint16_t subgroup,
+ bcmbal_apicli_prop_access_id access_level,
+ bcmcli_cmd_parm *parms,
+ uint32_t cmd_flags,
+ const char *prefix)
+{
+ int nf = 0;
+ int i;
+ bcmos_errno rc = BCM_ERR_OK;
+
+ for (i = 0; rc != BCM_ERR_RANGE; i++)
+ {
+ const bcmbal_apicli_prop_descr *pd;
+ char name_buf[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH] = "";
+ char help_buf[BCMBAL_APICLI_MAX_PARM_HELP_LENGTH] = "";
+
+ strncpy(name_buf, prefix, BCMBAL_APICLI_MAX_PARM_NAME_LENGTH-1);
+ name_buf[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH-1] = 0;
+
+ rc = bcmbal_apicli_object_property(o, group, subgroup, i, &pd);
+ if (rc == BCM_ERR_OK && (pd->access & access_level))
+ {
+ rc = bcmbal_apicli_populate_parms_from_property(pd, NULL, NULL, 0, 0, &parms[nf],
+ access_level, cmd_flags, name_buf, help_buf);
+ if (rc > 0)
+ nf += rc;
+ }
+ }
+ return nf;
+}
+
+
+/* compact selector table. squeeze out values that don't have parameter table attached */
+static void bcmbal_apicli_compact_selector(bcmcli_enum_val *selector, int size)
+{
+ int i, j;
+
+ for (i = 0; i < size; i++)
+ {
+ if (!selector[i].parms)
+ {
+ for ( j = i + 1; j < size && !selector[j].parms; j ++)
+ ;
+ if (j < size)
+ {
+ memcpy(&selector[i], &selector[j], sizeof(bcmcli_enum_val));
+ memset(&selector[j], 0, sizeof(bcmcli_enum_val));
+ }
+ else
+ {
+ memset(&selector[i], 0, sizeof(bcmcli_enum_val));
+ }
+ }
+ }
+}
+
+/* Free CLI parameters. both name and description are allocated dynamically */
+static void bcmbal_apicli_free_parms(bcmcli_cmd_parm *parms)
+{
+ bcmcli_cmd_parm *p = parms;
+
+ while (p->name)
+ {
+ if ((p->flags & BCMCLI_PARM_FLAG_SELECTOR))
+ {
+ /* Remove selector table */
+ bcmcli_enum_val *sel = p->enum_table;
+ if (sel)
+ {
+ bcmcli_enum_val *e = sel;
+ while(e->name)
+ {
+ if (e->parms)
+ {
+ bcmbal_apicli_free_parms(e->parms);
+ }
+ ++e;
+ }
+ bcmos_free(sel);
+ }
+ }
+ if (p->description)
+ bcmos_free(BCMBAL_APICLI_CAST_DISCARD_CONST(p->description, void *));
+ if (p->name)
+ bcmos_free(BCMBAL_APICLI_CAST_DISCARD_CONST(p->name, void *));
+ if (p->max_array_size && p->values)
+ bcmos_free(p->values);
+ if (p->value.buffer.start)
+ bcmbal_buf_free(&p->value.buffer);
+
+ ++p;
+ }
+ bcmos_free(parms);
+}
+
+static uint8_t bcmbal_apicli_get_num_cmd_parms(bcmbal_mgt_group group, bcmbal_apicli_flags flags)
+{
+ if (group == BCMBAL_MGT_GROUP_STAT)
+ return 2; /* object + stat ID */
+ else
+ return 1; /* object */
+}
+
+/* Read generated info and add CLI command */
+static bcmos_errno bcmbal_apicli_add(bcmcli_entry *dir, const char *cmd_name, const char *cmd_descr,
+ bcmbal_mgt_group group, bcmbal_apicli_prop_access_id access_level, bcmcli_cmd_cb cmd_handler,
+ bcmbal_apicli_flags flags)
+{
+ bcmcli_cmd_extra_parm cmd_extras = { .free_parms = bcmbal_apicli_free_parms };
+ bcmcli_cmd_parm *cmd_parms;
+ bcmcli_enum_val *obj_selector;
+ bcmbal_obj_id o;
+ bcmos_errno rc = BCM_ERR_OK;
+ uint32_t cmd_flags = 0;
+ uint8_t num_cmd_parms = bcmbal_apicli_get_num_cmd_parms(group, flags);
+ int n_obj;
+ int i;
+
+ /* Command flags: parameters in the following groups are optional */
+ if (group == BCMBAL_MGT_GROUP_CFG || group == BCMBAL_MGT_GROUP_STAT || group == BCMBAL_MGT_GROUP_AUTO_CFG)
+ cmd_flags = BCMCLI_PARM_FLAG_OPTIONAL;
+
+ /* command parameters are:
+ * - object_name (selector)
+ * - object_key_fields
+ * - object_per_group_fields filtered by access
+ * Therefore, there is 1 top-level enum parameter (object type) with per-value parameter tables
+ * In the case of operations or proxy messages, there is also a top-level enum parameter for the oper/proxy name
+ */
+
+ /* Allocate enum table based on max number of objects. Will be compacted in the end */
+ cmd_parms = bcmos_calloc(sizeof(bcmcli_cmd_parm) * (num_cmd_parms + 1));
+ if (!cmd_parms)
+ return BCM_ERR_NOMEM;
+
+ /* Allocate enough space for all object entries as well as a terminator entry (which is left NULL) */
+ obj_selector = bcmos_calloc(sizeof(bcmcli_enum_val) * (BCMBAL_OBJ_ID__NUM_OF + 1));
+ if (!obj_selector)
+ goto nomem_cleanup;
+
+ /* Allocate parameter table */
+ n_obj = 0;
+ for (o = 0; o < BCMBAL_OBJ_ID__NUM_OF; o++)
+ {
+ uint32_t nkeyfields = 0;
+ uint32_t nfields = 0;
+ uint32_t nfilterfields = 0;
+ uint32_t size;
+ uint16_t s;
+ uint16_t subgroup_count = bcmbal_apicli_get_subgroup_count(o, group);
+ bcmcli_enum_val *sub_selector;
+
+ if (subgroup_count == 0)
+ continue;
+
+ obj_selector[n_obj].val = o;
+ rc = bcmbal_apicli_object_name(o, &obj_selector[n_obj].name, NULL);
+ if (rc)
+ continue;
+
+ /* Get number of key fields and save it */
+ if (group == BCMBAL_MGT_GROUP_AUTO_CFG)
+ {
+ nkeyfields = 0;
+ }
+ else
+ {
+ bcmbal_apicli_get_num_fields_in_group(
+ o, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_APICLI_PROP_ACCESS_ID_W, &nkeyfields);
+ }
+
+ /* Allocate subgroup enum table */
+ sub_selector = bcmos_calloc(sizeof(bcmcli_enum_val) * (subgroup_count + 1));
+ if (!sub_selector)
+ goto nomem_cleanup;
+
+ /* Allocate single subgroup command parameter */
+ size = sizeof(bcmcli_cmd_parm) * 2;
+ obj_selector[n_obj].parms = bcmos_calloc(size);
+ if (!obj_selector[n_obj].parms)
+ {
+ bcmos_free(sub_selector);
+ goto nomem_cleanup;
+ }
+
+ /* Setup single subgroup command parameter */
+ obj_selector[n_obj].parms[0].type = BCMCLI_PARM_ENUM;
+ obj_selector[n_obj].parms[0].flags = BCMCLI_PARM_FLAG_SELECTOR;
+ obj_selector[n_obj].parms[0].enum_table = sub_selector;
+ rc = bcmbal_apicli_copy_parm_name(&obj_selector[n_obj].parms[0],
+ "sub",
+ "Subgroup (specific operation / proxy msg)");
+ if (rc)
+ goto nomem_cleanup;
+
+ for (s = 0; s < subgroup_count; ++s)
+ {
+ const char *sub_name;
+ bcmcli_cmd_parm *parm_ptr;
+
+ /* Get name of specific subgroup */
+ rc = bcmbal_apicli_object_subgroup_name(o, group, s, &sub_name, NULL);
+ if (rc)
+ continue;
+
+ /* Setup entry in subgroup enum table */
+ sub_selector[s].name = sub_name;
+ sub_selector[s].val = s;
+
+ /* Get number of group fields */
+ rc = bcmbal_apicli_get_num_fields_in_group(o, group, s, access_level, &nfields);
+ if (rc)
+ continue;
+
+ if ((flags & BCMBAL_APICLI_FLAGS_IGNORE_FIELDS) != BCMBAL_APICLI_FLAGS_NONE)
+ {
+ nfilterfields = 0;
+ nfields = 0;
+ }
+
+ /* Allocate parameter table and populate it */
+ sub_selector[s].parms = bcmbal_apicli_parm_alloc(nfields + nkeyfields + nfilterfields);
+ if (!sub_selector[s].parms)
+ {
+ rc = BCM_ERR_NOMEM;
+ goto nomem_cleanup;
+ }
+ for (i = 0; i < nkeyfields + nfields + nfilterfields; i++)
+ {
+ bcmbal_apicli_parm_data *parm_data = sub_selector[s].parms[i].user_data;
+ parm_data->group = (i < nkeyfields) ? BCMBAL_MGT_GROUP_KEY : group;
+ }
+
+ parm_ptr = sub_selector[s].parms;
+ if (nkeyfields)
+ {
+ rc = bcmbal_apicli_populate_parms(
+ o, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_APICLI_PROP_ACCESS_ID_W, parm_ptr, 0, "");
+ if (rc < 0)
+ goto nomem_cleanup;
+ parm_ptr += rc;
+ }
+ if (nfilterfields)
+ {
+ rc = bcmbal_apicli_populate_parms(
+ o, group, s, BCMBAL_APICLI_PROP_ACCESS_ID_RW, parm_ptr, cmd_flags, "filter.");
+ if (rc < 0)
+ goto nomem_cleanup;
+ parm_ptr += rc;
+ }
+ if (nfields)
+ {
+ rc = bcmbal_apicli_populate_parms(o, group, s, access_level, parm_ptr, cmd_flags, "");
+ if (rc < 0)
+ goto nomem_cleanup;
+ parm_ptr += rc;
+ }
+ }
+
+ /* Compact sub_selector enum. Removes holes (values without parameter table) */
+ bcmbal_apicli_compact_selector(sub_selector, subgroup_count);
+
+ /* If the group type doesn't support subgroups, remove the subgroup param entry */
+ if (group == BCMBAL_MGT_GROUP_CFG || group == BCMBAL_MGT_GROUP_STAT || group == BCMBAL_MGT_GROUP_AUTO_CFG)
+ {
+ /* Free the memory associated with the (single) subgroup param */
+ bcmos_free(BCMBAL_APICLI_CAST_DISCARD_CONST(obj_selector[n_obj].parms[0].name, void *));
+ bcmos_free(BCMBAL_APICLI_CAST_DISCARD_CONST(obj_selector[n_obj].parms[0].description, void *));
+ bcmos_free(obj_selector[n_obj].parms);
+ /* Assign the subgroup params to the root object params */
+ obj_selector[n_obj].parms = sub_selector[0].parms;
+ bcmos_free(sub_selector);
+ }
+
+ ++n_obj; /* number of configured objects */
+ }
+
+ /* Compact obj_selector enum. Removes holes (values without parameter table) */
+ bcmbal_apicli_compact_selector(obj_selector, BCMBAL_OBJ_ID__NUM_OF);
+
+ /* Add a 'clear on read' to stats group */
+ if (group == BCMBAL_MGT_GROUP_STAT)
+ {
+ cmd_parms[0].type = BCMCLI_PARM_ENUM;
+ cmd_parms[0].enum_table = bool_enum;
+ rc = bcmbal_apicli_copy_parm_name(&cmd_parms[0], "clear", "clear on read");
+ if (rc)
+ goto nomem_cleanup;
+ }
+
+ /* We are ready to add this command */
+ cmd_parms[num_cmd_parms - 1].type = BCMCLI_PARM_ENUM;
+ cmd_parms[num_cmd_parms - 1].flags = BCMCLI_PARM_FLAG_SELECTOR;
+ cmd_parms[num_cmd_parms - 1].enum_table = obj_selector;
+ rc = bcmbal_apicli_copy_parm_name(&cmd_parms[num_cmd_parms - 1], "object", "Object Type");
+ if (rc)
+ goto nomem_cleanup;
+ rc = bcmcli_cmd_add(dir, cmd_name, cmd_handler, cmd_descr,
+ (access_level == BCMBAL_APICLI_PROP_ACCESS_ID_W) ? BCMCLI_ACCESS_ADMIN : BCMCLI_ACCESS_GUEST,
+ &cmd_extras, cmd_parms);
+ if (rc)
+ goto nomem_cleanup;
+ return 0;
+
+nomem_cleanup:
+ if (obj_selector)
+ {
+ for (o = 0; o < BCMBAL_OBJ_ID__NUM_OF; o++)
+ {
+ if (obj_selector[o].parms)
+ bcmbal_apicli_free_parms(obj_selector[o].parms);
+ }
+ bcmos_free(obj_selector);
+ }
+ bcmos_free(cmd_parms);
+ return rc;
+}
+
+static bcmcli_session *bcmbal_apicli_log;
+static FILE *bcmbal_apicli_log_file;
+
+static int bcmbal_apicli_log_write_cb(bcmcli_session *session, const char *buf, uint32_t size)
+{
+ if (bcmbal_apicli_log_file == NULL || buf == NULL)
+ return BCM_ERR_INTERNAL;
+ fwrite(buf, 1, size, bcmbal_apicli_log_file);
+ fflush(bcmbal_apicli_log_file);
+ return BCM_ERR_OK;
+}
+
+/* Enable/disable API logging
+ * BCMCLI_MAKE_PARM("file", "Log file. Use \"-\" to disable logging", BCMCLI_PARM_STRING, 0));
+ */
+static bcmos_errno bcmbal_apicli_log_handler(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
+{
+ const char *fname = parm[0].value.string;
+ bcmcli_session_parm session_params =
+ {
+ .write = bcmbal_apicli_log_write_cb,
+ .name = "api_log"
+ };
+ bcmos_errno rc;
+ time_t start_time;
+
+ /* Close existing log session if any */
+ if (bcmbal_apicli_log)
+ {
+ bcmcli_log_set(BCMCLI_LOG_NONE, NULL);
+ bcmcli_session_close(bcmbal_apicli_log);
+ fclose(bcmbal_apicli_log_file);
+ bcmbal_apicli_log = NULL;
+ bcmbal_apicli_log_file = NULL;
+ }
+
+ if (!strcmp(fname, "-"))
+ return BCM_ERR_OK;
+
+ /* Starting a new log session */
+ bcmbal_apicli_log_file = fopen(fname, "a");
+ if (bcmbal_apicli_log_file == NULL)
+ {
+ bcmcli_print(session, "Can't open file %s for logging\n", fname);
+ return BCM_ERR_PARM;
+ }
+ rc = bcmcli_session_open_user(&session_params, &bcmbal_apicli_log);
+ if (rc)
+ {
+ fclose(bcmbal_apicli_log_file);
+ bcmbal_apicli_log_file = NULL;
+ bcmcli_print(session, "Can't open log session. Error %s\n", bcmos_strerror(rc));
+ return rc;
+ }
+ time(&start_time);
+ bcmcli_log_set(BCMCLI_LOG_C_COMMENT, bcmbal_apicli_log);
+ bcmcli_log("/* API logging session started. %s */\n", ctime(&start_time));
+ return BCM_ERR_OK;
+}
+
+static void bcmbal_apicli_find_del_cmd(bcmcli_entry *dir, const char *cmd_name)
+{
+ bcmcli_entry *cmd;
+ cmd = bcmcli_cmd_find(dir, cmd_name);
+ if (cmd)
+ {
+ bcmcli_token_destroy(cmd);
+ }
+}
+
+/* Unregisters commands and directories */
+void bcmbal_apicli_del_commands(bcmcli_session *session, bcmcli_entry *api_dir)
+{
+ bcmbal_apicli_find_del_cmd(api_dir, "set");
+ bcmbal_apicli_find_del_cmd(api_dir, "get");
+ bcmbal_apicli_find_del_cmd(api_dir, "clear");
+ bcmbal_apicli_find_del_cmd(api_dir, "stat");
+ bcmbal_apicli_find_del_cmd(api_dir, "objects");
+ bcmbal_apicli_find_del_cmd(api_dir, "log");
+}
+
+/* Registers commands and directories */
+bcmos_errno bcmbal_apicli_add_commands(bcmcli_session *session, bcmcli_entry *api_dir)
+{
+ bcmos_errno rc;
+
+ current_session = session;
+
+ /* Now generate and add commands */
+ rc = bcmbal_apicli_add(api_dir, "set", "Set object configuration", BCMBAL_MGT_GROUP_CFG,
+ BCMBAL_APICLI_PROP_ACCESS_ID_W, bcmbal_apicli_set_handler, BCMBAL_APICLI_FLAGS_NONE);
+ rc = rc ? rc : bcmbal_apicli_add(api_dir, "get", "Get object configuration", BCMBAL_MGT_GROUP_CFG,
+ BCMBAL_APICLI_PROP_ACCESS_ID_R, bcmbal_apicli_get_handler, BCMBAL_APICLI_FLAGS_NONE);
+ rc = rc ? rc : bcmbal_apicli_add(api_dir, "clear", "Clear object configuration", BCMBAL_MGT_GROUP_CFG,
+ BCMBAL_APICLI_PROP_ACCESS_ID_R, bcmbal_apicli_clear_handler, BCMBAL_APICLI_FLAGS_IGNORE_FIELDS);
+ rc = rc ? rc : bcmbal_apicli_add(api_dir, "stat", "Get statistics", BCMBAL_MGT_GROUP_STAT,
+ BCMBAL_APICLI_PROP_ACCESS_ID_R, bcmbal_apicli_stat_handler, BCMBAL_APICLI_FLAGS_NONE);
+
+ /* List all system objects */
+ rc = rc ? rc : bcmcli_cmd_add(api_dir, "objects", bcmbal_apicli_objects_handler,
+ "Object Types", BCMCLI_ACCESS_GUEST, NULL, NULL);
+
+ BCMCLI_MAKE_CMD(api_dir, "log", "Log API calls", bcmbal_apicli_log_handler,
+ BCMCLI_MAKE_PARM("file", "Log file. Use \"-\" to disable logging", BCMCLI_PARM_STRING, 0));
+
+ return rc;
+}
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli.h b/bal_release/src/lib/libbalapicli/bal_api_cli.h
new file mode 100644
index 0000000..2acc2a7
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli.h
@@ -0,0 +1,40 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(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 BCMBAL_APICLI_H_
+#define BCMBAL_APICLI_H_
+
+#include <bcmcli.h>
+
+void bcmbal_apicli_del_commands(bcmcli_session *session, bcmcli_entry *api_dir);
+
+/* Add BAL CLI commands */
+bcmos_errno bcmbal_apicli_add_commands(bcmcli_session *session, bcmcli_entry *api_dir);
+
+#endif /* BCMBAL_APICLI_H_ */
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli_dump.c b/bal_release/src/lib/libbalapicli/bal_api_cli_dump.c
new file mode 100644
index 0000000..5a34961
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli_dump.c
@@ -0,0 +1,823 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(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 <bcmos_system.h>
+#include <bal_obj.h>
+#include <bcmcli.h>
+#include "bal_api_cli_helpers.h"
+
+typedef enum
+{
+ BCMBAL_APICLI_OUTPUT_STYLE_STD,
+ BCMBAL_APICLI_OUTPUT_STYLE_C_INIT
+} bcmbal_apicli_output_style;
+
+typedef struct
+{
+ const bcmbal_apicli_type_descr *type;
+ void *data;
+ uint8_t bit;
+} bcmbal_apicli_presence_mask_info;
+
+static bcmos_errno bcmbal_apicli_dump_array(
+ bcmcli_session *session,
+ const bcmbal_apicli_type_descr *td,
+ void *data,
+ uint32_t size,
+ const char *name,
+ bcmbal_apicli_output_style style,
+ const bcmbal_apicli_presence_mask_info *presence_mask);
+
+static bcmos_errno bcmbal_apicli_read_snum(
+ bcmcli_session *session, const bcmbal_apicli_type_descr *td, void *data, int64_t *n)
+{
+ switch (td->size)
+ {
+ case 1:
+ {
+ int8_t n1 = *(int8_t *)data;
+ *n = n1;
+ break;
+ }
+ case 2:
+ {
+ int16_t n2 = *(int16_t *)data;
+ *n = n2;
+ break;
+ }
+ case 4:
+ {
+ int32_t n4 = *(int32_t *)data;
+ *n = n4;
+ break;
+ }
+ case 8:
+ {
+ memcpy(n, data, sizeof(*n));
+ break;
+ }
+ default:
+ bcmcli_print(session, "*** number size %u is not supported\n", td->size);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcmbal_apicli_read_unum(
+ bcmcli_session *session, const bcmbal_apicli_type_descr *td, void *data, uint64_t *n)
+{
+ switch (td->size)
+ {
+ case 1:
+ {
+ uint8_t n1 = *(uint8_t *)data;
+ *n = n1;
+ break;
+ }
+ case 2:
+ {
+ uint16_t n2 = *(uint16_t *)data;
+ *n = n2;
+ break;
+ }
+ case 4:
+ {
+ uint32_t n4 = *(uint32_t *)data;
+ *n = n4;
+ break;
+ }
+ case 8:
+ {
+ memcpy(n, data, sizeof(*n));
+ break;
+ }
+ default:
+ bcmcli_print(session, "*** number size %u is not supported\n", td->size);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ return BCM_ERR_OK;
+}
+
+static void bcmbal_apicli_strcat_upper(char *dest, uint32_t dest_len, const char *src, uint32_t src_len)
+{
+ uint32_t src_idx;
+ uint32_t dest_idx;
+
+ for (dest_idx = 0; dest_idx < dest_len - 1; ++dest_idx)
+ {
+ if (dest[dest_idx] == '\0')
+ {
+ break;
+ }
+ }
+
+ for (src_idx = 0; src_idx < src_len && dest_idx < dest_len - 1; ++src_idx, ++dest_idx)
+ {
+ dest[dest_idx] = src[src_idx];
+ if (dest[dest_idx] >= 'a' && dest[dest_idx] <= 'z')
+ {
+ dest[dest_idx] = 'A' + (dest[dest_idx] - 'a');
+ }
+ }
+
+ dest[dest_idx] = '\0';
+}
+
+static const char *bcmbal_apicli_get_c_enum_id(const bcmbal_apicli_type_descr *td, const char *name)
+{
+ static char full_name_buf[256];
+ full_name_buf[0] = '\0';
+ bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), td->name, strlen(td->name));
+ bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), "_", 1);
+ bcmbal_apicli_strcat_upper(full_name_buf, sizeof(full_name_buf), name, strlen(name));
+ return full_name_buf;
+}
+
+static bcmos_errno bcmbal_apicli_dump_simple_data_type(
+ bcmcli_session *session,
+ const bcmbal_apicli_type_descr *td,
+ void *data,
+ const char *name,
+ bcmbal_apicli_output_style style)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ switch (td->base_type)
+ {
+ case BCMBAL_APICLI_BASE_TYPE_ID_SNUM: /* signed number */
+ {
+ int64_t n = 0;
+ rc = bcmbal_apicli_read_snum(session, td, data, &n);
+ bcmcli_print(session, "%lld", (long long)n);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_UNUM: /* unsigned number */
+ {
+ uint64_t n = 0;
+ rc = bcmbal_apicli_read_unum(session, td, data, &n);
+ bcmcli_print(session, "%llu", (unsigned long long)n);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX: /* unsigned number printed in hex */
+ {
+ uint64_t n = 0;
+ rc = bcmbal_apicli_read_unum(session, td, data, &n);
+ bcmcli_print(session, "0x%llx", (unsigned long long)n);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_FLOAT: /* floating-point number */
+ {
+ if (td->size == sizeof(float))
+ {
+ bcmcli_print(session, "%f", *(float *)data);
+ }
+ else if (td->size == sizeof(double))
+ {
+ bcmcli_print(session, "%f", *(double *)data);
+ }
+ else
+ {
+ bcmcli_print(session, "*** floating-point number of width %u is not supported\n", td->size);
+ rc = BCM_ERR_NOT_SUPPORTED;
+ }
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_BOOL:
+ {
+ const char *no_str = style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "BCMOS_FALSE" : "no";
+ const char *yes_str = style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "BCMOS_TRUE" : "yes";
+ uint64_t n = 0;
+ rc = bcmbal_apicli_read_unum(session, td, data, &n);
+ bcmcli_print(session, "%s", n == 0 ? no_str : yes_str);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_STRING: /* string */
+ {
+ if (td->size == 0)
+ {
+ bcmcli_print(session, "\"%s\"", (char *)data);
+ }
+ else
+ {
+ /* we know the size of the buffer */
+ bcmcli_print(session, "\"%.*s\"", td->size, (char *)data);
+ }
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_IPV4: /* IPv4 address */
+ {
+ uint32_t ip;
+ memcpy(&ip, data, sizeof(ip));
+ bcmcli_print(
+ session,
+ style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "{ %d,%d,%d,%d }" : "%d.%d.%d.%d",
+ (ip >> 24) & 0xff, (ip >> 16) & 0xff, (ip >> 8) & 0xff, ip & 0xff);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_MAC: /* MAC address */
+ {
+ bcmos_mac_address mac;
+ memcpy(mac.u8, data, sizeof(mac.u8));
+ bcmcli_print(
+ session,
+ style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ?
+ "{{ 0x%02x,0x%02x,0x%02x,0x%02x,0x%02x,0x%02x }}" :
+ "%02x:%02x:%02x:%02x:%02x:%02x",
+ mac.u8[0], mac.u8[1], mac.u8[2], mac.u8[3], mac.u8[4], mac.u8[5]);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_ENUM: /* enum */
+ {
+ uint64_t n = 0;
+ const char *s;
+ rc = bcmbal_apicli_read_unum(session, td, data, &n);
+ BUG_ON(td->x.e == NULL);
+ s = bcmcli_enum_stringval(td->x.e, (long)n);
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ s = bcmbal_apicli_get_c_enum_id(td, s);
+ }
+ bcmcli_print(session, "%s", s);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK:
+ {
+ uint64_t n = 0;
+ const char *s;
+ const char *none = NULL;
+ bcmcli_enum_val *value = td->x.e;
+ bcmos_bool first = BCMOS_TRUE;
+ BUG_ON(value == NULL);
+ rc = bcmbal_apicli_read_unum(session, td, data, &n);
+ while (value->name != NULL)
+ {
+ if (value->val == 0)
+ {
+ none = value->name;
+ }
+ if ((value->val & n) != 0)
+ {
+ s = value->name;
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ s = bcmbal_apicli_get_c_enum_id(td, s);
+ }
+ bcmcli_print(session, "%s%s", first ? "" : (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT ? "|" : BCMCLI_ENUM_MASK_DEL_STR), s);
+ first = BCMOS_FALSE;
+ n -= value->val;
+ }
+ ++value;
+ }
+ if (first)
+ {
+ bcmcli_print(session, "%s", (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT) || (NULL == none) ? "0" : none);
+ }
+ break;
+ }
+
+ default:
+ bcmcli_print(session, "*** type %d is not supported\n", (int)td->base_type);
+ rc = BCM_ERR_NOT_SUPPORTED;
+ break;
+ }
+ return rc;
+}
+
+
+/* calculate number of enum values */
+static int bcmbal_apicli_get_num_enum_vals(const bcmcli_enum_val *vals)
+{
+ const bcmcli_enum_val *v = vals;
+ while (v && v->name)
+ {
+ ++v;
+ }
+ return (v - vals);
+}
+
+/* helper function to skip the "u." in front of union field names */
+static inline const char *bcmbal_apicli_skip_union_prefix(const char *name)
+{
+ if (name[0] == 'u' && name[1] == '.')
+ {
+ name += 2;
+ }
+ return name;
+}
+
+static bcmos_bool bcmbal_apicli_is_value_set(
+ bcmcli_session *session,
+ const bcmbal_apicli_presence_mask_info *presence_mask)
+{
+ uint64_t pm_value_num = 0;
+ if (!presence_mask || !presence_mask->type)
+ {
+ /* no presence mask - all values are implicitly set */
+ return BCMOS_TRUE;
+ }
+ bcmbal_apicli_read_unum(session, presence_mask->type, presence_mask->data, &pm_value_num);
+ return ((pm_value_num >> presence_mask->bit) & 1) != 0;
+}
+
+/* Dump data type */
+static bcmos_errno bcmbal_apicli_dump_data_type(
+ bcmcli_session *session,
+ const bcmbal_apicli_type_descr *td,
+ void *data,
+ const char *name,
+ uint32_t num_entries,
+ uint32_t entry_size,
+ bcmbal_apicli_output_style style,
+ const bcmbal_apicli_presence_mask_info *presence_mask)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ switch (td->base_type)
+ {
+ case BCMBAL_APICLI_BASE_TYPE_ID_STRUCT:
+ {
+ uint16_t f;
+ char full_name[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
+ if (!td->x.s.num_fields)
+ return 0;
+ BUG_ON(!td->x.s.fields);
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, "{ ");
+ }
+ for (f = 0; f < td->x.s.num_fields; f++)
+ {
+ const bcmbal_apicli_field_descr *fld = &td->x.s.fields[f];
+ void *fdata = (void *)((long)data + fld->offset);
+ bcmbal_apicli_presence_mask_info field_pm = {};
+ if (((td->x.s.fields[0].flags & BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK) != 0) &&
+ style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ /* If the struct has a presence mask, skip the presence mask field itself, then record the position
+ * of the presence mask so we can check it later for each entry. */
+ if (f == 0)
+ {
+ continue;
+ }
+
+ field_pm.type = td->x.s.fields[0].type;
+ field_pm.data = (uint8_t *)data + td->x.s.fields[0].offset;
+ field_pm.bit = (uint8_t)(f - 1);
+ }
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT && f > 0)
+ {
+ bcmcli_print(session, ", ");
+ }
+ bcmcli_strncpy(full_name, name, sizeof(full_name));
+ bcmcli_strncat(full_name, ".", sizeof(full_name));
+ bcmcli_strncat(full_name, fld->name, sizeof(full_name));
+ rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, &field_pm);
+ }
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, " }");
+ }
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_UNION:
+ {
+ /* Print fields up to selector, then selector, then selected sub-structure */
+ uint16_t f;
+ char full_name[BCMBAL_APICLI_MAX_PARM_NAME_LENGTH];
+ const bcmbal_apicli_field_descr *fld;
+ void *fdata;
+ int64_t selector_val = 0;
+ int num_union_vals;
+
+ if (!td->x.u.num_common_fields)
+ return 0;
+ BUG_ON(!td->x.u.common_fields);
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, "{ ");
+ }
+ /* Common fields, including selector */
+ for (f = 0; f <= td->x.u.classifier_idx && !rc; f++)
+ {
+ fld = &td->x.u.common_fields[f];
+ fdata = (void *)((long)data + fld->offset);
+
+ bcmcli_strncpy(full_name, name, sizeof(full_name));
+ if (fld->name && strlen(fld->name))
+ {
+ bcmcli_strncat(full_name, ".", sizeof(full_name));
+ bcmcli_strncat(full_name, fld->name, sizeof(full_name));
+ }
+ rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
+ if (f == td->x.u.classifier_idx)
+ {
+ rc = rc ? rc : bcmbal_apicli_read_snum(session, fld->type, fdata, &selector_val);
+ }
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, ", ");
+ }
+ }
+ if (rc)
+ {
+ bcmcli_print(session, "***internal error when dumping field %s\n",
+ td->x.u.common_fields[f].name);
+ return rc;
+ }
+
+ num_union_vals = bcmbal_apicli_get_num_enum_vals(td->x.u.common_fields[td->x.u.classifier_idx].type->x.e);
+ if ((unsigned)selector_val >= num_union_vals)
+ {
+ bcmcli_print(session, "***invalid union selector value %lld\n", (long long)selector_val);
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* Common fields following selector */
+ for (; f < td->x.u.num_common_fields; f++)
+ {
+ fld = &td->x.u.common_fields[f];
+ fdata = (void *)((long)data + fld->offset);
+
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, ", ");
+ }
+ bcmcli_strncpy(full_name, name, sizeof(full_name));
+ if (fld->name && strlen(fld->name))
+ {
+ bcmcli_strncat(full_name, ".", sizeof(full_name));
+ bcmcli_strncat(full_name, fld->name, sizeof(full_name));
+ }
+ rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
+ }
+
+ /* Selected field */
+ fld = &td->x.u.union_fields[selector_val];
+ if (fld->type)
+ {
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, "{ .%s = ", bcmbal_apicli_skip_union_prefix(fld->name));
+ }
+ fdata = (void *)((long)data + fld->offset);
+
+ bcmcli_strncpy(full_name, name, sizeof(full_name));
+ if (fld->name && strlen(fld->name))
+ {
+ bcmcli_strncat(full_name, ".", sizeof(full_name));
+ bcmcli_strncat(full_name, fld->name, sizeof(full_name));
+ }
+ rc = bcmbal_apicli_dump_data_type(session, fld->type, fdata, full_name, num_entries, entry_size, style, presence_mask);
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, " }");
+ }
+ }
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, " }");
+ }
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED: /* fixed array */
+ {
+ rc = bcmbal_apicli_dump_array(session, td->x.arr_fixed.elem_type, data, td->x.arr_fixed.size, name, style, presence_mask);
+ break;
+ }
+
+ case BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN: /* dynamic array that should be printed as buffer */
+ {
+ /* Read length */
+ uint32_t array_size;
+ long base_ptr;
+
+ switch (td->x.arr_dyn.len_size )
+ {
+ case 1: array_size = *(uint8_t *)data; break;
+ case 2: array_size = *(uint16_t *)data; break;
+ case 4: array_size = *(uint32_t *)data; break;
+ default:
+ bcmcli_print(session,
+ "*** %s: dyn array len_size %u is not supported\n", name, td->x.arr_dyn.len_size);
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+ base_ptr = BCMOS_ROUND_UP((long)data + td->x.arr_dyn.len_size, sizeof(void *));
+ BUG_ON(!base_ptr);
+ data = *(void **)base_ptr;
+ rc = bcmbal_apicli_dump_array(session, td->x.arr_dyn.elem_type, data, array_size, name, style, presence_mask);
+ break;
+ }
+
+ default:
+ {
+ /* Finally! Simple type that maps to a single CLI parameter */
+ int n;
+ bcmbal_apicli_presence_mask_info local_pm;
+
+ /* If we have a single value and that value is not included in the presence mask, just skip it entirely */
+ if (num_entries == 1 && !bcmbal_apicli_is_value_set(session, presence_mask))
+ {
+ break;
+ }
+
+ if (style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ if (name)
+ {
+ bcmcli_print(session, " %s=", name);
+ }
+ if (!num_entries)
+ {
+ bcmcli_print(session, BCMCLI_ARRAY_EMPTY);
+ }
+ }
+
+ /* Dump simple value or array of simple values */
+ local_pm = presence_mask ? *presence_mask : (bcmbal_apicli_presence_mask_info){};
+ for (n = 0; n < num_entries; n++)
+ {
+ if (n)
+ {
+ bcmcli_print(session, ",");
+ }
+
+ /* If we have a presence mask, make sure to print a special token if the value is unset */
+ if (bcmbal_apicli_is_value_set(session, &local_pm))
+ {
+ rc = bcmbal_apicli_dump_simple_data_type(session, td, data, name, style);
+ }
+ else
+ {
+ bcmcli_print(session, BCMCLI_PARM_NO_VALUE);
+ }
+
+ data = (void *)((long)data + entry_size);
+ local_pm.data = (void *)((long)local_pm.data + entry_size);
+ }
+ if (style != BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, "\n");
+ }
+ break;
+ }
+ }
+ return rc;
+}
+
+/* Dump array */
+static bcmos_errno bcmbal_apicli_dump_array(
+ bcmcli_session *session,
+ const bcmbal_apicli_type_descr *td,
+ void *data,
+ uint32_t size,
+ const char *name,
+ bcmbal_apicli_output_style style,
+ const bcmbal_apicli_presence_mask_info *presence_mask)
+{
+ bcmos_errno rc = BCM_ERR_OK;
+
+ /* Print as buffer or element by element ? */
+ if (style == BCMBAL_APICLI_OUTPUT_STYLE_C_INIT)
+ {
+ bcmcli_print(session, "{ ");
+ rc = bcmbal_apicli_dump_data_type(session, td, data, name, size, td->size, style, presence_mask);
+ bcmcli_print(session, " }");
+ }
+ else if ((td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM ||
+ td->base_type == BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX) && td->size == 1)
+ {
+ if (bcmbal_apicli_is_value_set(session, presence_mask))
+ {
+ bcmcli_print(session, " %s=\n", name);
+ bcmcli_session_hexdump(session, data, 0, size, " ");
+ }
+ }
+ else
+ {
+ rc = bcmbal_apicli_dump_data_type(session, td, data, name, size, td->size, style, presence_mask);
+ }
+ return rc;
+}
+
+/* Dump property */
+bcmos_errno bcmbal_apicli_dump_prop(bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data)
+{
+ return bcmbal_apicli_dump_data_type(
+ session, pd->type, prop_data, pd->name, 1, 0, BCMBAL_APICLI_OUTPUT_STYLE_STD, NULL);
+}
+
+/* Dump a single property value in C initializer format */
+bcmos_errno bcmbal_apicli_dump_prop_initializer(
+ bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data)
+{
+ return bcmbal_apicli_dump_data_type(
+ session, pd->type, prop_data, pd->name, 1, 0, BCMBAL_APICLI_OUTPUT_STYLE_C_INIT, NULL);
+}
+
+/* Calculate property pointer given the group data pointer and property description */
+static inline void *bcmbal_apicli_prop_data_ptr(void *group_ptr, const bcmbal_apicli_prop_descr *pd)
+{
+ return (void *)((long)group_ptr + pd->offset);
+}
+
+/* Dump object data */
+static bcmos_errno bcmbal_apicli_dump_data(bcmcli_session *session, bcmbal_obj *msg, void *data, uint32_t data_size)
+{
+ uint16_t prop;
+ bcmos_errno rc = BCM_ERR_OK;
+ const bcmbal_apicli_prop_descr *pd;
+
+ bcmcli_print(session, "data:\n");
+ for (prop = 0;
+ bcmbal_apicli_object_property(msg->obj_type, msg->group, msg->subgroup, prop, &pd) == BCM_ERR_OK;
+ ++prop)
+ {
+ void *prop_data = bcmbal_apicli_prop_data_ptr(data, pd);
+ if (!(msg->presence_mask & (1LL << prop)))
+ continue;
+ if (!prop_data)
+ {
+ continue;
+ }
+ BUG_ON(pd->offset > data_size);
+ rc = bcmbal_apicli_dump_prop(session, pd, prop_data);
+ if (rc != BCM_ERR_OK)
+ {
+ break;
+ }
+ }
+ return rc;
+}
+
+/* Dump object key */
+static bcmos_errno bcmbal_apicli_dump_key(bcmcli_session *session, bcmbal_obj *msg, void *key, uint32_t key_size)
+{
+ uint16_t prop;
+ bcmos_errno rc = BCM_ERR_OK;
+ const bcmbal_apicli_prop_descr *pd;
+
+ bcmcli_print(session, "key:\n");
+ for (prop = 0;
+ bcmbal_apicli_object_property(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, prop, &pd) == BCM_ERR_OK;
+ ++prop)
+ {
+ void *prop_data = bcmbal_apicli_prop_data_ptr(key, pd);
+ if (!prop_data)
+ {
+ continue;
+ }
+ BUG_ON(pd->offset > key_size);
+ rc = bcmbal_apicli_dump_prop(session, pd, prop_data);
+ if (rc != BCM_ERR_OK)
+ {
+ break;
+ }
+ }
+ return rc;
+}
+
+const char *bcmbal_apicli_mgt_group_to_str(bcmbal_mgt_group group)
+{
+ static const char *str_table[BCMBAL_MGT_GROUP__NUM_OF] =
+ {
+ [BCMBAL_MGT_GROUP_KEY] = "key",
+ [BCMBAL_MGT_GROUP_CFG] = "cfg",
+ [BCMBAL_MGT_GROUP_STAT] = "stat",
+ [BCMBAL_MGT_GROUP_AUTO] = "auto",
+ [BCMBAL_MGT_GROUP_AUTO_CFG] = "auto_cfg",
+ };
+ return (group >= BCMBAL_MGT_GROUP__NUM_OF) ? "<unknown>" : str_table[group];
+}
+
+/* Dump message */
+bcmos_errno bcmbal_apicli_msg_dump(bcmcli_session *session, bcmbal_obj *msg)
+{
+ bcmos_errno rc;
+ const char *name, *descr;
+ uint32_t key_size;
+ uint32_t key_offset;
+ uint32_t data_size = 0;
+ uint32_t data_offset;
+ void *key = NULL;
+ void *data = NULL;
+
+ rc = bcmbal_apicli_object_name(msg->obj_type, &name, &descr);
+ if (rc)
+ {
+ goto dump_error;
+ }
+
+ bcmcli_print(session, "object: ");
+ if (name)
+ {
+ bcmcli_print(session, "%s", name);
+ }
+ if (descr)
+ {
+ bcmcli_print(session, " - %s", descr);
+ }
+ bcmcli_print(session, "\n");
+ rc = bcmbal_apicli_object_struct_size(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, &key_size, &key_offset, &data_size, &data_offset);
+ rc = rc ? rc : bcmbal_apicli_object_struct_size(msg->obj_type, msg->group, msg->subgroup, &key_size, &key_offset, &data_size, &data_offset);
+ if (rc)
+ {
+ goto dump_error;
+ }
+
+ bcmcli_print(session, (msg->type & BCMBAL_OBJ_MSG_TYPE_GET) != 0 ? "get" : "set");
+ if ((msg->type & BCMBAL_OBJ_MSG_TYPE_CLEAR) != 0)
+ {
+ bcmcli_print(session, ",clear");
+ }
+ bcmcli_print(session, " %s ", bcmbal_apicli_mgt_group_to_str(msg->group));
+
+ if (msg->group != BCMBAL_MGT_GROUP_CFG &&
+ msg->group != BCMBAL_MGT_GROUP_STAT &&
+ msg->group != BCMBAL_MGT_GROUP_AUTO_CFG)
+ {
+ const char *sub_name, *sub_descr;
+ /* Get name of specific subgroup */
+ rc = bcmbal_apicli_object_subgroup_name(msg->obj_type, msg->group, msg->subgroup, &sub_name, &sub_descr);
+ if (rc)
+ {
+ goto dump_error;
+ }
+ bcmcli_print(session, "subgroup: %s-%s ", sub_name ? sub_name : "?", sub_descr ? sub_descr : "");
+ }
+ if (msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST)
+ {
+ bcmcli_print(session, "request\n");
+ }
+ else
+ {
+ bcmcli_print(session, "response: %s\n", bcmos_strerror(msg->status));
+ bcmcli_print(session, "is in-progress: %s\n", (msg->is_inprogress == BCMOS_TRUE) ? "yes" : "no");
+ }
+
+ if ((msg->group != BCMBAL_MGT_GROUP_AUTO_CFG) && key_size)
+ {
+ key = (void *)((long)msg + sizeof(bcmbal_obj));
+ rc = bcmbal_apicli_dump_key(session, msg, key, key_size);
+ if (rc)
+ {
+ goto dump_error;
+ }
+ }
+ if (data_size &&
+ ( ((msg->dir == BCMBAL_OBJ_MSG_DIR_REQUEST) && (msg->type & BCMBAL_OBJ_MSG_TYPE_SET)) ||
+ ((msg->dir == BCMBAL_OBJ_MSG_DIR_RESPONSE) && (msg->type & BCMBAL_OBJ_MSG_TYPE_GET)) ||
+ (msg->group == BCMBAL_MGT_GROUP_AUTO)
+ )
+ )
+ {
+ data = (void *)((long)msg + data_offset);
+ rc = bcmbal_apicli_dump_data(session, msg, data, data_size);
+ if (rc)
+ {
+ goto dump_error;
+ }
+ }
+ return BCM_ERR_OK;
+
+dump_error:
+ bcmcli_print(session, "*** Object dump error %s (%d)\n", bcmos_strerror(rc), rc);
+ return rc;
+}
+
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli_handlers.c b/bal_release/src/lib/libbalapicli/bal_api_cli_handlers.c
new file mode 100644
index 0000000..cc90bbf
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli_handlers.c
@@ -0,0 +1,4516 @@
+#include <bcmos_system.h>
+#include <bal_api.h>
+#include <bcmcli.h>
+#include "bal_api_cli_helpers.h"
+#include "bal_api_cli_handlers.h"
+
+bcmcli_session *bcmbal_apicli_log_session = NULL;
+
+typedef struct
+{
+ uint8_t *start;
+ uint32_t used;
+} bcmbal_apicli_byte_pool;
+
+static bcmos_errno bcmbal_apicli_byte_pool_create(bcmbal_apicli_byte_pool *buf)
+{
+ buf->used = 0;
+ buf->start = bcmos_calloc(BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ return (buf->start == NULL) ? BCM_ERR_NOMEM : BCM_ERR_OK;
+}
+
+static void bcmbal_apicli_byte_pool_destroy(bcmbal_apicli_byte_pool *buf)
+{
+ bcmos_free(buf->start);
+}
+
+static void *bcmbal_apicli_byte_pool_calloc(bcmbal_apicli_byte_pool *buf, uint32_t num_bytes)
+{
+ void *ret;
+ if (buf->used + num_bytes > BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE)
+ {
+ return NULL;
+ }
+
+ ret = buf->start + buf->used;
+ buf->used += num_bytes;
+ memset(ret, 0, num_bytes);
+ return ret;
+}
+
+/*
+ * Start/end banners - these are specially formatted so listening apps can easily tell where API handling starts/ends.
+ */
+static void bcmbal_apicli_print_start(bcmcli_session *session, const char *api_name)
+{
+ bcmcli_print(session, "[-- API Start: %s --]\n", api_name);
+}
+
+static void bcmbal_apicli_print_data_start(bcmcli_session *session)
+{
+ bcmcli_print(session, "[-- API Message Data --]\n");
+}
+
+static void bcmbal_apicli_print_complete(bcmcli_session *session, bcmos_errno err, const char *err_text)
+{
+ if (err != BCM_ERR_OK && err_text != NULL && err_text[0] != '\0')
+ {
+ bcmcli_print(session, "ERROR: %s", err_text);
+ }
+
+ bcmcli_print(session, "[-- API Complete: %d (%s) --]\n", err, bcmos_strerror(err));
+}
+
+static int bcmbal_apicli_session_write_cb(bcmcli_session *cli_session, const char *buf, uint32_t size)
+{
+ bcmcli_log(buf, "%.*s", size, buf);
+ return (int)size;
+}
+
+/* Logs a property value to the CLI log in such a way that it is a valid RHS in an initializer. For a primitve, this
+ * will just print the value (e.g. "42"). For a struct, it will emit all members in between curly braces. */
+static void bcmbal_apicli_log_prop_val(bcmolt_obj_id obj, bcmolt_mgt_group group, uint16_t subgroup, uint16_t prop, void *value)
+{
+ bcmos_errno err;
+ const bcmbal_apicli_prop_descr *prop_descr;
+
+ if (bcmbal_apicli_log_session == NULL)
+ {
+ static bcmcli_session_parm session_params = { .write = bcmbal_apicli_session_write_cb };
+
+ err = bcmcli_session_open(&session_params, &bcmbal_apicli_log_session);
+ if (err != BCM_ERR_OK)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error opening session: %s", bcmos_strerror(err));
+ return;
+ }
+ }
+
+ err = bcmbal_apicli_object_property(obj, group, subgroup, prop, &prop_descr);
+ if (err != BCM_ERR_OK)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error getting info for property: %s", bcmos_strerror(err));
+ return;
+ }
+
+ err = bcmbal_apicli_dump_prop_initializer(bcmbal_apicli_log_session, prop_descr, value);
+ if (err != BCM_ERR_OK)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error printing property: %s", bcmos_strerror(err));
+ }
+}
+
+static inline bcmos_ipv4_address bcmbal_apicli_unumber_to_ipv4(uint32_t num)
+{
+ bcmos_ipv4_address ip = { .u32 = num };
+ return ip;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_access_terminal_cfg_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_access_terminal_cfg cfg; /**< declare main API struct */
+ bcmbal_access_terminal_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_access_terminal_cfg cfg;\n");
+ bcmcli_log("bcmbal_access_terminal_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, access_terminal, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, access_terminal, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, access_terminal, admin_state);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, access_terminal, admin_state);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "oper_status");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, access_terminal, oper_status);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, access_terminal, oper_status);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "iwf_mode");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, access_terminal, iwf_mode);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, access_terminal, iwf_mode);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, access_terminal, admin_state) && !BCMBAL_CFG_PROP_IS_SET(&cfg, access_terminal, oper_status) && !BCMBAL_CFG_PROP_IS_SET(&cfg, access_terminal, iwf_mode))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, access_terminal, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, access_terminal, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_access_terminal_cfg_set(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_access_terminal_cfg cfg; /**< declare main API struct */
+ bcmbal_access_terminal_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_access_terminal_cfg cfg;\n");
+ bcmcli_log("bcmbal_access_terminal_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, access_terminal, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, access_terminal, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ bcmbal_state val;
+ val = (bcmbal_state) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, access_terminal, admin_state, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, access_terminal, admin_state, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_ACCESS_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE, &val);
+ bcmcli_log(");\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_access_terminal_cfg_clear(bcmcli_session *session)
+{
+ bcmos_errno err;
+ bcmbal_access_terminal_cfg cfg; /**< declare main API struct */
+ bcmbal_access_terminal_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_access_terminal_cfg cfg;\n");
+ bcmcli_log("bcmbal_access_terminal_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, access_terminal, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, access_terminal, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_flow_cfg_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_flow_cfg cfg; /**< declare main API struct */
+ bcmbal_flow_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_flow_cfg cfg;\n");
+ bcmcli_log("bcmbal_flow_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "flow_id");
+ if (cli_parm != NULL)
+ {
+ key.flow_id = (bcmbal_flow_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_ID, &key.flow_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "flow_type");
+ if (cli_parm != NULL)
+ {
+ key.flow_type = (bcmbal_flow_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_TYPE, &key.flow_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, flow, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, flow, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, admin_state);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, admin_state);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "oper_status");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, oper_status);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, oper_status);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "access_int_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, access_int_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, access_int_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "network_int_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, network_int_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, network_int_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, sub_term_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, sub_term_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_uni_idx");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, sub_term_uni_idx);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, sub_term_uni_idx);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "svc_port_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, svc_port_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, svc_port_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "agg_port_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, agg_port_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, agg_port_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "resolve_mac");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, resolve_mac);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, resolve_mac);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, classifier);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, classifier);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, action);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, action);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sla");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, sla);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, sla);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "cookie");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, cookie);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, cookie);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "priority");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, priority);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, priority);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "group_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, group_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, group_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "queue");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, queue);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, queue);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, flow, admin_state) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, oper_status) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, access_int_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, network_int_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, sub_term_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, sub_term_uni_idx) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, svc_port_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, agg_port_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, resolve_mac) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, classifier) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, action) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, sla) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, cookie) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, priority) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, group_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, flow, queue))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, flow, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, flow, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_flow_cfg_set(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_flow_cfg cfg; /**< declare main API struct */
+ bcmbal_flow_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_flow_cfg cfg;\n");
+ bcmcli_log("bcmbal_flow_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "flow_id");
+ if (cli_parm != NULL)
+ {
+ key.flow_id = (bcmbal_flow_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_ID, &key.flow_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "flow_type");
+ if (cli_parm != NULL)
+ {
+ key.flow_type = (bcmbal_flow_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_TYPE, &key.flow_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, flow, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, flow, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ bcmbal_state val;
+ val = (bcmbal_state) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, admin_state, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, admin_state, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_ADMIN_STATE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "access_int_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_intf_id val;
+ val = (bcmbal_intf_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, access_int_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, access_int_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "network_int_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_intf_id val;
+ val = (bcmbal_intf_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, network_int_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, network_int_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_sub_id val;
+ val = (bcmbal_sub_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_SUB_TERM_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_uni_idx");
+ if (cli_parm != NULL)
+ {
+ uint8_t val;
+ val = cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_uni_idx, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, sub_term_uni_idx, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "svc_port_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_service_port_id val;
+ val = (bcmbal_service_port_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, svc_port_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, svc_port_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_SVC_PORT_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "agg_port_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_aggregation_port_id val;
+ val = (bcmbal_aggregation_port_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, agg_port_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, agg_port_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_AGG_PORT_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "resolve_mac");
+ if (cli_parm != NULL)
+ {
+ bcmos_bool val;
+ val = cli_parm->value.number;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, resolve_mac, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, resolve_mac, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_RESOLVE_MAC, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "classifier.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_classifier val = { };
+ cli_parm = bcmcli_find_named_parm(session, "classifier.o_tpid");
+ if (cli_parm != NULL)
+ {
+ val.o_tpid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_O_TPID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.o_vid");
+ if (cli_parm != NULL)
+ {
+ val.o_vid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_O_VID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.i_tpid");
+ if (cli_parm != NULL)
+ {
+ val.i_tpid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_I_TPID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.i_vid");
+ if (cli_parm != NULL)
+ {
+ val.i_vid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_I_VID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.o_pbits");
+ if (cli_parm != NULL)
+ {
+ val.o_pbits = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_O_PBITS;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.i_pbits");
+ if (cli_parm != NULL)
+ {
+ val.i_pbits = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_I_PBITS;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.ether_type");
+ if (cli_parm != NULL)
+ {
+ val.ether_type = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_ETHER_TYPE;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.dst_mac");
+ if (cli_parm != NULL)
+ {
+ val.dst_mac = cli_parm->value.mac;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_DST_MAC;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.src_mac");
+ if (cli_parm != NULL)
+ {
+ val.src_mac = cli_parm->value.mac;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_SRC_MAC;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.ip_proto");
+ if (cli_parm != NULL)
+ {
+ val.ip_proto = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_IP_PROTO;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.dst_ip");
+ if (cli_parm != NULL)
+ {
+ val.dst_ip = bcmbal_apicli_unumber_to_ipv4(cli_parm->value.unumber);
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_DST_IP;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.src_ip");
+ if (cli_parm != NULL)
+ {
+ val.src_ip = bcmbal_apicli_unumber_to_ipv4(cli_parm->value.unumber);
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_SRC_IP;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.src_port");
+ if (cli_parm != NULL)
+ {
+ val.src_port = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_SRC_PORT;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.dst_port");
+ if (cli_parm != NULL)
+ {
+ val.dst_port = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_DST_PORT;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "classifier.pkt_tag_type");
+ if (cli_parm != NULL)
+ {
+ val.pkt_tag_type = (bcmbal_pkt_tag_type) cli_parm->value.enum_val;
+ val.presence_mask = val.presence_mask | BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, flow, classifier, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_classifier val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_CLASSIFIER, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, classifier, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "action.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_action val = { };
+ cli_parm = bcmcli_find_named_parm(session, "action.cmds_bitmask");
+ if (cli_parm != NULL)
+ {
+ val.cmds_bitmask = (bcmbal_action_cmd_id) cli_parm->value.enum_val;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_CMDS_BITMASK;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action.o_vid");
+ if (cli_parm != NULL)
+ {
+ val.o_vid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_O_VID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action.o_pbits");
+ if (cli_parm != NULL)
+ {
+ val.o_pbits = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_O_PBITS;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action.o_tpid");
+ if (cli_parm != NULL)
+ {
+ val.o_tpid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_O_TPID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action.i_vid");
+ if (cli_parm != NULL)
+ {
+ val.i_vid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_I_VID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action.i_pbits");
+ if (cli_parm != NULL)
+ {
+ val.i_pbits = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_I_PBITS;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "action.i_tpid");
+ if (cli_parm != NULL)
+ {
+ val.i_tpid = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_ACTION_ID_I_TPID;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, flow, action, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_action val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_ACTION, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, action, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "sla.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_sla val = { };
+ cli_parm = bcmcli_find_named_parm(session, "sla.min_rate");
+ if (cli_parm != NULL)
+ {
+ val.min_rate = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_SLA_ID_MIN_RATE;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sla.max_rate");
+ if (cli_parm != NULL)
+ {
+ val.max_rate = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_SLA_ID_MAX_RATE;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, flow, sla, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_sla val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_SLA, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, sla, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "cookie");
+ if (cli_parm != NULL)
+ {
+ bcmbal_cookie val;
+ val = (bcmbal_cookie) cli_parm->value.unumber64;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, cookie, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, cookie, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_COOKIE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "priority");
+ if (cli_parm != NULL)
+ {
+ uint16_t val;
+ val = cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, priority, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, priority, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_PRIORITY, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "group_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_group_id val;
+ val = (bcmbal_group_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, flow, group_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, group_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_GROUP_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "queue.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_queue_ref val = { };
+ cli_parm = bcmcli_find_named_parm(session, "queue.sched_id");
+ if (cli_parm != NULL)
+ {
+ val.sched_id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "queue.sched_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "queue.queue_id");
+ if (cli_parm != NULL)
+ {
+ val.queue_id = (bcmbal_tm_queue_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "queue.queue_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, flow, queue, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_queue_ref val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_FLOW_CFG_ID_QUEUE, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, flow, queue, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_flow_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_flow_cfg cfg; /**< declare main API struct */
+ bcmbal_flow_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_flow_cfg cfg;\n");
+ bcmcli_log("bcmbal_flow_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "flow_id");
+ if (cli_parm != NULL)
+ {
+ key.flow_id = (bcmbal_flow_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_ID, &key.flow_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "flow_type");
+ if (cli_parm != NULL)
+ {
+ key.flow_type = (bcmbal_flow_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_TYPE, &key.flow_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, flow, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, flow, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_flow_stat_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_flow_stat stat; /**< declare main API struct */
+ bcmbal_flow_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_flow_stat stat;\n");
+ bcmcli_log("bcmbal_flow_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_stat_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "flow_id");
+ if (cli_parm != NULL)
+ {
+ key.flow_id = (bcmbal_flow_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_ID, &key.flow_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "flow_type");
+ if (cli_parm != NULL)
+ {
+ key.flow_type = (bcmbal_flow_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "flow_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.flow_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_FLOW_KEY_ID_FLOW_TYPE, &key.flow_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_STAT_INIT(&stat, flow, key);
+ bcmcli_log("BCMBAL_STAT_INIT(&stat, flow, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "rx_packets");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, flow, rx_packets);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, flow, rx_packets);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rx_bytes");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, flow, rx_bytes);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, flow, rx_bytes);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tx_packets");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, flow, tx_packets);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, flow, tx_packets);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tx_bytes");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, flow, tx_bytes);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, flow, tx_bytes);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_STAT_PROP_IS_SET(&stat, flow, rx_packets) && !BCMBAL_STAT_PROP_IS_SET(&stat, flow, rx_bytes) && !BCMBAL_STAT_PROP_IS_SET(&stat, flow, tx_packets) && !BCMBAL_STAT_PROP_IS_SET(&stat, flow, tx_bytes))
+ {
+ BCMBAL_STAT_PROP_GET(&stat, flow, all_properties);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, flow, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_stat_get(&stat.hdr);
+ bcmcli_log("bcmbal_stat_get(&stat.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &stat.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_group_cfg_get(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_group_cfg cfg; /**< declare main API struct */
+ bcmbal_group_key key = { }; /**< declare key */
+ uint8_t *list_mem; /**< declare memory buffer for variable-sized lists */
+ bcmcli_log("bcmbal_group_cfg cfg;\n");
+ bcmcli_log("bcmbal_group_key key = { };\n");
+ bcmcli_log("uint8_t* list_mem;\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "group_id");
+ if (cli_parm != NULL)
+ {
+ key.group_id = (bcmbal_group_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "group_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.group_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_GROUP_KEY_ID_GROUP_ID, &key.group_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, group, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, group, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "members_cmd");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, group, members_cmd);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, group, members_cmd);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, group, members);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, group, members);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "cookie");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, group, cookie);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, group, cookie);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flows");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, group, flows);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, group, flows);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, group, owner);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, group, owner);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, group, members_cmd) && !BCMBAL_CFG_PROP_IS_SET(&cfg, group, members) && !BCMBAL_CFG_PROP_IS_SET(&cfg, group, cookie) && !BCMBAL_CFG_PROP_IS_SET(&cfg, group, flows) && !BCMBAL_CFG_PROP_IS_SET(&cfg, group, owner))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, group, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, group, all_properties);\n");
+ }
+
+ /* set memory to use for variable-sized lists */
+ list_mem = bcmbal_apicli_byte_pool_calloc(byte_pool, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ if (list_mem == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmcli_log("list_mem = bcmos_calloc(BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+ BCMBAL_CFG_LIST_BUF_SET(&cfg, group, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ bcmcli_log("BCMBAL_CFG_LIST_BUF_SET(&cfg, group, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_group_cfg_set(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_group_cfg cfg; /**< declare main API struct */
+ bcmbal_group_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_group_cfg cfg;\n");
+ bcmcli_log("bcmbal_group_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "group_id");
+ if (cli_parm != NULL)
+ {
+ key.group_id = (bcmbal_group_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "group_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.group_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_GROUP_KEY_ID_GROUP_ID, &key.group_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, group, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, group, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "members_cmd");
+ if (cli_parm != NULL)
+ {
+ bcmbal_group_member_cmd val;
+ val = (bcmbal_group_member_cmd) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, group, members_cmd, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, group, members_cmd, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_GROUP_CFG_ID_MEMBERS_CMD, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "members.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_group_member_info_list_u16 val = { };
+ int32_t i0;
+ val.val = bcmbal_apicli_byte_pool_calloc(byte_pool, cli_parm->array_size * sizeof(*val.val));
+ if (val.val == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ val.len = cli_parm->array_size;
+ cli_parm = bcmcli_find_named_parm(session, "members.intf_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.intf_id is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ val.val[i0].intf_id = (bcmbal_intf_id) cli_parm->values[i0].unumber;
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.svc_port_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.svc_port_id is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ val.val[i0].svc_port_id = (bcmbal_service_port_id) cli_parm->values[i0].unumber;
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.cmds_bitmask");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.cmds_bitmask is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.cmds_bitmask = (bcmbal_action_cmd_id) cli_parm->values[i0].enum_val;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_CMDS_BITMASK;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.o_vid");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.o_vid is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.o_vid = cli_parm->values[i0].unumber;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_O_VID;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.o_pbits");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.o_pbits is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.o_pbits = cli_parm->values[i0].unumber;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_O_PBITS;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.o_tpid");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.o_tpid is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.o_tpid = cli_parm->values[i0].unumber;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_O_TPID;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.i_vid");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.i_vid is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.i_vid = cli_parm->values[i0].unumber;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_I_VID;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.i_pbits");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.i_pbits is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.i_pbits = cli_parm->values[i0].unumber;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_I_PBITS;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.action.i_tpid");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.action.i_tpid is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ if (bcmcli_parm_value_is_set(session, cli_parm, i0))
+ {
+ val.val[i0].action.i_tpid = cli_parm->values[i0].unumber;
+ val.val[i0].action.presence_mask = val.val[i0].action.presence_mask | BCMBAL_ACTION_ID_I_TPID;
+ }
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.queue.sched_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.queue.sched_id is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ val.val[i0].queue.sched_id = (bcmbal_tm_sched_id) cli_parm->values[i0].unumber;
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "members.queue.queue_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->array_size != val.len)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "members.queue.queue_id is a different size than other arrays in the struct\n");
+ return BCM_ERR_PARM;
+ }
+
+ for (i0 = 0; i0 < val.len; i0++)
+ {
+ val.val[i0].queue.queue_id = (bcmbal_tm_queue_id) cli_parm->values[i0].unumber;
+ }
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, group, members, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_group_member_info_list_u16 val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_GROUP_CFG_ID_MEMBERS, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, group, members, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "cookie");
+ if (cli_parm != NULL)
+ {
+ bcmbal_cookie val;
+ val = (bcmbal_cookie) cli_parm->value.unumber64;
+ BCMBAL_CFG_PROP_SET(&cfg, group, cookie, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, group, cookie, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_GROUP_CFG_ID_COOKIE, &val);
+ bcmcli_log(");\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_group_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_group_cfg cfg; /**< declare main API struct */
+ bcmbal_group_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_group_cfg cfg;\n");
+ bcmcli_log("bcmbal_group_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "group_id");
+ if (cli_parm != NULL)
+ {
+ key.group_id = (bcmbal_group_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "group_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.group_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_GROUP_KEY_ID_GROUP_ID, &key.group_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, group, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, group, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_interface_cfg_get(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_interface_cfg cfg; /**< declare main API struct */
+ bcmbal_interface_key key = { }; /**< declare key */
+ uint8_t *list_mem; /**< declare memory buffer for variable-sized lists */
+ bcmcli_log("bcmbal_interface_cfg cfg;\n");
+ bcmcli_log("bcmbal_interface_key key = { };\n");
+ bcmcli_log("uint8_t* list_mem;\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_type");
+ if (cli_parm != NULL)
+ {
+ key.intf_type = (bcmbal_intf_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_TYPE, &key.intf_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, interface, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, interface, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, admin_state);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, admin_state);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "oper_status");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, oper_status);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, oper_status);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "min_data_agg_port_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, min_data_agg_port_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, min_data_agg_port_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "min_data_svc_port_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, min_data_svc_port_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, min_data_svc_port_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "transceiver_type");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, transceiver_type);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, transceiver_type);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ds_miss_mode");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, ds_miss_mode);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, ds_miss_mode);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "mtu");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, mtu);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, mtu);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flow_control");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, flow_control);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, flow_control);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ds_tm");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, ds_tm);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, ds_tm);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "us_tm");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, us_tm);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, us_tm);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id_list");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, sub_term_id_list);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, sub_term_id_list);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, interface, admin_state) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, oper_status) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, min_data_agg_port_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, min_data_svc_port_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, transceiver_type) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, ds_miss_mode) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, mtu) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, flow_control) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, ds_tm) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, us_tm) && !BCMBAL_CFG_PROP_IS_SET(&cfg, interface, sub_term_id_list))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, interface, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, interface, all_properties);\n");
+ }
+
+ /* set memory to use for variable-sized lists */
+ list_mem = bcmbal_apicli_byte_pool_calloc(byte_pool, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ if (list_mem == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmcli_log("list_mem = bcmos_calloc(BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+ BCMBAL_CFG_LIST_BUF_SET(&cfg, interface, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ bcmcli_log("BCMBAL_CFG_LIST_BUF_SET(&cfg, interface, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_interface_cfg_set(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_interface_cfg cfg; /**< declare main API struct */
+ bcmbal_interface_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_interface_cfg cfg;\n");
+ bcmcli_log("bcmbal_interface_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_type");
+ if (cli_parm != NULL)
+ {
+ key.intf_type = (bcmbal_intf_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_TYPE, &key.intf_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, interface, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, interface, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ bcmbal_state val;
+ val = (bcmbal_state) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, admin_state, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, admin_state, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "min_data_agg_port_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_aggregation_port_id val;
+ val = (bcmbal_aggregation_port_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, min_data_agg_port_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, min_data_agg_port_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "min_data_svc_port_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_service_port_id val;
+ val = (bcmbal_service_port_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, min_data_svc_port_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, min_data_svc_port_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "transceiver_type");
+ if (cli_parm != NULL)
+ {
+ bcmbal_trx_type val;
+ val = (bcmbal_trx_type) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, transceiver_type, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, transceiver_type, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ds_miss_mode");
+ if (cli_parm != NULL)
+ {
+ bcmbal_ds_miss_mode val;
+ val = (bcmbal_ds_miss_mode) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, ds_miss_mode, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, ds_miss_mode, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "mtu");
+ if (cli_parm != NULL)
+ {
+ uint16_t val;
+ val = cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, mtu, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, mtu, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_MTU, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flow_control");
+ if (cli_parm != NULL)
+ {
+ bcmbal_control val;
+ val = (bcmbal_control) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, flow_control, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, flow_control, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ds_tm");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_id val;
+ val = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, ds_tm, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, ds_tm, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_DS_TM, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "us_tm");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_id val;
+ val = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, interface, us_tm, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, interface, us_tm, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_INTERFACE_CFG_ID_US_TM, &val);
+ bcmcli_log(");\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_interface_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_interface_cfg cfg; /**< declare main API struct */
+ bcmbal_interface_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_interface_cfg cfg;\n");
+ bcmcli_log("bcmbal_interface_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_type");
+ if (cli_parm != NULL)
+ {
+ key.intf_type = (bcmbal_intf_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_TYPE, &key.intf_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, interface, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, interface, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_interface_stat_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_interface_stat stat; /**< declare main API struct */
+ bcmbal_interface_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_interface_stat stat;\n");
+ bcmcli_log("bcmbal_interface_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_stat_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_type");
+ if (cli_parm != NULL)
+ {
+ key.intf_type = (bcmbal_intf_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_type = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_INTERFACE_KEY_ID_INTF_TYPE, &key.intf_type);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_STAT_INIT(&stat, interface, key);
+ bcmcli_log("BCMBAL_STAT_INIT(&stat, interface, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "rx_packets");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, interface, rx_packets);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, interface, rx_packets);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rx_bytes");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, interface, rx_bytes);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, interface, rx_bytes);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tx_packets");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, interface, tx_packets);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, interface, tx_packets);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tx_bytes");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, interface, tx_bytes);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, interface, tx_bytes);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_STAT_PROP_IS_SET(&stat, interface, rx_packets) && !BCMBAL_STAT_PROP_IS_SET(&stat, interface, rx_bytes) && !BCMBAL_STAT_PROP_IS_SET(&stat, interface, tx_packets) && !BCMBAL_STAT_PROP_IS_SET(&stat, interface, tx_bytes))
+ {
+ BCMBAL_STAT_PROP_GET(&stat, interface, all_properties);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, interface, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_stat_get(&stat.hdr);
+ bcmcli_log("bcmbal_stat_get(&stat.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &stat.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_packet_cfg_get(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_packet_cfg cfg; /**< declare main API struct */
+ bcmbal_packet_key key = { }; /**< declare key */
+ uint8_t *list_mem; /**< declare memory buffer for variable-sized lists */
+ bcmcli_log("bcmbal_packet_cfg cfg;\n");
+ bcmcli_log("bcmbal_packet_key key = { };\n");
+ bcmcli_log("uint8_t* list_mem;\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "reserved");
+ if (cli_parm != NULL)
+ {
+ key.reserved = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "reserved is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.reserved = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_PACKET_KEY_ID_RESERVED, &key.reserved);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_parm_by_prefix(session, "packet_send_dest.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.type");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.type = (bcmbal_dest_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ switch (key.packet_send_dest.type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.int_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.nni.int_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.int_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.sub_term_uni");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.sub_term_uni = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.sub_term_uni is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.int_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.int_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.int_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ break;
+ default:
+ bcmbal_apicli_print_complete(session, BCM_ERR_RANGE, "\n");
+ return BCM_ERR_RANGE;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.packet_send_dest = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST, &key.packet_send_dest);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, packet, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, packet, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "flow_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, flow_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, flow_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flow_type");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, flow_type);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, flow_type);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, intf_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, intf_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "intf_type");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, intf_type);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, intf_type);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "svc_port");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, svc_port);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, svc_port);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flow_cookie");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, flow_cookie);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, flow_cookie);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "pkt");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, pkt);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, pkt);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, packet, flow_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, packet, flow_type) && !BCMBAL_CFG_PROP_IS_SET(&cfg, packet, intf_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, packet, intf_type) && !BCMBAL_CFG_PROP_IS_SET(&cfg, packet, svc_port) && !BCMBAL_CFG_PROP_IS_SET(&cfg, packet, flow_cookie) && !BCMBAL_CFG_PROP_IS_SET(&cfg, packet, pkt))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, packet, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, packet, all_properties);\n");
+ }
+
+ /* set memory to use for variable-sized lists */
+ list_mem = bcmbal_apicli_byte_pool_calloc(byte_pool, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ if (list_mem == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmcli_log("list_mem = bcmos_calloc(BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+ BCMBAL_CFG_LIST_BUF_SET(&cfg, packet, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ bcmcli_log("BCMBAL_CFG_LIST_BUF_SET(&cfg, packet, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_packet_cfg_set(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_packet_cfg cfg; /**< declare main API struct */
+ bcmbal_packet_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_packet_cfg cfg;\n");
+ bcmcli_log("bcmbal_packet_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "reserved");
+ if (cli_parm != NULL)
+ {
+ key.reserved = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "reserved is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.reserved = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_PACKET_KEY_ID_RESERVED, &key.reserved);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_parm_by_prefix(session, "packet_send_dest.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.type");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.type = (bcmbal_dest_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ switch (key.packet_send_dest.type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.int_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.nni.int_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.int_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.sub_term_uni");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.sub_term_uni = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.sub_term_uni is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.int_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.int_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.int_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ break;
+ default:
+ bcmbal_apicli_print_complete(session, BCM_ERR_RANGE, "\n");
+ return BCM_ERR_RANGE;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.packet_send_dest = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST, &key.packet_send_dest);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, packet, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, packet, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "flow_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_flow_id val;
+ val = (bcmbal_flow_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, packet, flow_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, flow_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_FLOW_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flow_type");
+ if (cli_parm != NULL)
+ {
+ bcmbal_flow_type val;
+ val = (bcmbal_flow_type) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, packet, flow_type, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, flow_type, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_FLOW_TYPE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ bcmbal_intf_id val;
+ val = (bcmbal_intf_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, packet, intf_id, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, intf_id, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_INTF_ID, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "intf_type");
+ if (cli_parm != NULL)
+ {
+ bcmbal_intf_type val;
+ val = (bcmbal_intf_type) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, packet, intf_type, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, intf_type, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_INTF_TYPE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "svc_port");
+ if (cli_parm != NULL)
+ {
+ bcmbal_service_port_id val;
+ val = (bcmbal_service_port_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, packet, svc_port, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, svc_port, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_SVC_PORT, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "flow_cookie");
+ if (cli_parm != NULL)
+ {
+ bcmbal_cookie val;
+ val = (bcmbal_cookie) cli_parm->value.unumber64;
+ BCMBAL_CFG_PROP_SET(&cfg, packet, flow_cookie, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, flow_cookie, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_FLOW_COOKIE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "pkt");
+ if (cli_parm != NULL)
+ {
+ bcmbal_u8_list_u32 val = { };
+ val.len = bcmbal_buf_get_used(&cli_parm->value.buffer);
+ val.val = bcmbal_apicli_byte_pool_calloc(byte_pool, val.len);
+ if (val.val == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmbal_buf_set_pos(&cli_parm->value.buffer, 0);
+ bcmbal_buf_read(&cli_parm->value.buffer, val.val, val.len);
+ BCMBAL_CFG_PROP_SET(&cfg, packet, pkt, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_u8_list_u32 val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_PACKET_CFG_ID_PKT, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, packet, pkt, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_packet_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_packet_cfg cfg; /**< declare main API struct */
+ bcmbal_packet_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_packet_cfg cfg;\n");
+ bcmcli_log("bcmbal_packet_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "reserved");
+ if (cli_parm != NULL)
+ {
+ key.reserved = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "reserved is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.reserved = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_PACKET_KEY_ID_RESERVED, &key.reserved);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_parm_by_prefix(session, "packet_send_dest.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.type");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.type = (bcmbal_dest_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ switch (key.packet_send_dest.type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.int_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.nni.int_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.int_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.sub_term_uni");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.sub_term_uni = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.sub_term_uni is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packet_send_dest.int_id");
+ if (cli_parm != NULL)
+ {
+ key.packet_send_dest.u.sub_term.int_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest.int_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ break;
+ default:
+ bcmbal_apicli_print_complete(session, BCM_ERR_RANGE, "\n");
+ return BCM_ERR_RANGE;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "packet_send_dest is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.packet_send_dest = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST, &key.packet_send_dest);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, packet, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, packet, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_subscriber_terminal_cfg_get(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_subscriber_terminal_cfg cfg; /**< declare main API struct */
+ bcmbal_subscriber_terminal_key key = { }; /**< declare key */
+ uint8_t *list_mem; /**< declare memory buffer for variable-sized lists */
+ bcmcli_log("bcmbal_subscriber_terminal_cfg cfg;\n");
+ bcmcli_log("bcmbal_subscriber_terminal_key key = { };\n");
+ bcmcli_log("uint8_t* list_mem;\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sub_term_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID, &key.sub_term_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, admin_state);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, admin_state);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "oper_status");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, oper_status);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, oper_status);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "serial_number");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, serial_number);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, serial_number);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "password");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, password);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, password);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "registration_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, registration_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, registration_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "svc_port_id");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, svc_port_id);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, svc_port_id);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "mac_address");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, mac_address);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, mac_address);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ds_tm");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, ds_tm);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, ds_tm);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "us_tm");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, us_tm);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, us_tm);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "svc_port_id_list");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, svc_port_id_list);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, svc_port_id_list);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "agg_port_id_list");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, agg_port_id_list);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, agg_port_id_list);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, admin_state) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, oper_status) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, serial_number) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, password) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, registration_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, svc_port_id) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, mac_address) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, ds_tm) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, us_tm) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, svc_port_id_list) && !BCMBAL_CFG_PROP_IS_SET(&cfg, subscriber_terminal, agg_port_id_list))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, subscriber_terminal, all_properties);\n");
+ }
+
+ /* set memory to use for variable-sized lists */
+ list_mem = bcmbal_apicli_byte_pool_calloc(byte_pool, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ if (list_mem == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmcli_log("list_mem = bcmos_calloc(BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+ BCMBAL_CFG_LIST_BUF_SET(&cfg, subscriber_terminal, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ bcmcli_log("BCMBAL_CFG_LIST_BUF_SET(&cfg, subscriber_terminal, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_subscriber_terminal_cfg_set(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_subscriber_terminal_cfg cfg; /**< declare main API struct */
+ bcmbal_subscriber_terminal_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_subscriber_terminal_cfg cfg;\n");
+ bcmcli_log("bcmbal_subscriber_terminal_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sub_term_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID, &key.sub_term_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "admin_state");
+ if (cli_parm != NULL)
+ {
+ bcmbal_state val;
+ val = (bcmbal_state) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, admin_state, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, admin_state, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "serial_number.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_serial_number val = { };
+ cli_parm = bcmcli_find_named_parm(session, "serial_number.vendor_id");
+ if (cli_parm != NULL)
+ {
+ if (bcmbal_buf_get_used(&cli_parm->value.buffer) != 4)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "buffer serial_number.vendor_id must have 4 bytes\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmbal_buf_set_pos(&cli_parm->value.buffer, 0);
+ bcmbal_buf_read(&cli_parm->value.buffer, val.vendor_id, 4);
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "serial_number.vendor_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "serial_number.vendor_specific");
+ if (cli_parm != NULL)
+ {
+ if (bcmbal_buf_get_used(&cli_parm->value.buffer) != 4)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "buffer serial_number.vendor_specific must have 4 bytes\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmbal_buf_set_pos(&cli_parm->value.buffer, 0);
+ bcmbal_buf_read(&cli_parm->value.buffer, val.vendor_specific, 4);
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "serial_number.vendor_specific is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, serial_number, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_serial_number val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, serial_number, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "password.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_password val = { };
+ cli_parm = bcmcli_find_named_parm(session, "password.arr");
+ if (cli_parm != NULL)
+ {
+ if (bcmbal_buf_get_used(&cli_parm->value.buffer) != 10)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "buffer password.arr must have 10 bytes\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmbal_buf_set_pos(&cli_parm->value.buffer, 0);
+ bcmbal_buf_read(&cli_parm->value.buffer, val.arr, 10);
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "password.arr is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, password, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_password val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, password, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "registration_id.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_registration_id val = { };
+ cli_parm = bcmcli_find_named_parm(session, "registration_id.arr");
+ if (cli_parm != NULL)
+ {
+ if (bcmbal_buf_get_used(&cli_parm->value.buffer) != 36)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "buffer registration_id.arr must have 36 bytes\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmbal_buf_set_pos(&cli_parm->value.buffer, 0);
+ bcmbal_buf_read(&cli_parm->value.buffer, val.arr, 36);
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "registration_id.arr is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, registration_id, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_registration_id val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, registration_id, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "mac_address");
+ if (cli_parm != NULL)
+ {
+ bcmos_mac_address val;
+ val = cli_parm->value.mac;
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, mac_address, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, mac_address, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ds_tm");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_id val;
+ val = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, ds_tm, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, ds_tm, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "us_tm");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_id val;
+ val = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, us_tm, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, subscriber_terminal, us_tm, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM, &val);
+ bcmcli_log(");\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_subscriber_terminal_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_subscriber_terminal_cfg cfg; /**< declare main API struct */
+ bcmbal_subscriber_terminal_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_subscriber_terminal_cfg cfg;\n");
+ bcmcli_log("bcmbal_subscriber_terminal_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sub_term_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID, &key.sub_term_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, subscriber_terminal, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_subscriber_terminal_stat_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_subscriber_terminal_stat stat; /**< declare main API struct */
+ bcmbal_subscriber_terminal_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_subscriber_terminal_stat stat;\n");
+ bcmcli_log("bcmbal_subscriber_terminal_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_stat_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sub_term_id");
+ if (cli_parm != NULL)
+ {
+ key.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sub_term_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID, &key.sub_term_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "intf_id");
+ if (cli_parm != NULL)
+ {
+ key.intf_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.intf_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID, &key.intf_id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_STAT_INIT(&stat, subscriber_terminal, key);
+ bcmcli_log("BCMBAL_STAT_INIT(&stat, subscriber_terminal, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "rx_packets");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, rx_packets);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, rx_packets);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rx_bytes");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, rx_bytes);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, rx_bytes);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tx_packets");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, tx_packets);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, tx_packets);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tx_bytes");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, tx_bytes);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, tx_bytes);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_STAT_PROP_IS_SET(&stat, subscriber_terminal, rx_packets) && !BCMBAL_STAT_PROP_IS_SET(&stat, subscriber_terminal, rx_bytes) && !BCMBAL_STAT_PROP_IS_SET(&stat, subscriber_terminal, tx_packets) && !BCMBAL_STAT_PROP_IS_SET(&stat, subscriber_terminal, tx_bytes))
+ {
+ BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, all_properties);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, subscriber_terminal, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_stat_get(&stat.hdr);
+ bcmcli_log("bcmbal_stat_get(&stat.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &stat.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_queue_cfg_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_queue_cfg cfg; /**< declare main API struct */
+ bcmbal_tm_queue_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_tm_queue_cfg cfg;\n");
+ bcmcli_log("bcmbal_tm_queue_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sched_id");
+ if (cli_parm != NULL)
+ {
+ key.sched_id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID, &key.sched_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "sched_dir");
+ if (cli_parm != NULL)
+ {
+ key.sched_dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR, &key.sched_dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_queue_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, tm_queue, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, tm_queue, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "priority");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, priority);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, priority);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "weight");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, weight);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, weight);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rate");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, rate);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, rate);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, bac);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, bac);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "creation_mode");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, creation_mode);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, creation_mode);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "ref_count");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, ref_count);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, ref_count);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, tm_queue, priority) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_queue, weight) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_queue, rate) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_queue, bac) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_queue, creation_mode) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_queue, ref_count))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_queue, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_queue, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_queue_cfg_set(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_queue_cfg cfg; /**< declare main API struct */
+ bcmbal_tm_queue_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_tm_queue_cfg cfg;\n");
+ bcmcli_log("bcmbal_tm_queue_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sched_id");
+ if (cli_parm != NULL)
+ {
+ key.sched_id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID, &key.sched_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "sched_dir");
+ if (cli_parm != NULL)
+ {
+ key.sched_dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR, &key.sched_dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_queue_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, tm_queue, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, tm_queue, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "priority");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_priority val;
+ val = (bcmbal_tm_priority) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, tm_queue, priority, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_queue, priority, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_QUEUE_CFG_ID_PRIORITY, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "weight");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_weight val;
+ val = (bcmbal_tm_weight) cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, tm_queue, weight, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_queue, weight, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_QUEUE_CFG_ID_WEIGHT, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "rate.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_shaping val = { };
+ cli_parm = bcmcli_find_named_parm(session, "rate.sbr");
+ if (cli_parm != NULL)
+ {
+ val.sbr = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SHAPING_ID_SBR;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rate.pbr");
+ if (cli_parm != NULL)
+ {
+ val.pbr = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SHAPING_ID_PBR;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rate.burst");
+ if (cli_parm != NULL)
+ {
+ val.burst = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SHAPING_ID_BURST;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, tm_queue, rate, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_shaping val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_QUEUE_CFG_ID_RATE, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_queue, rate, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "bac.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_bac val = { };
+ cli_parm = bcmcli_find_named_parm(session, "bac.type");
+ if (cli_parm != NULL)
+ {
+ val.type = (bcmbal_tm_bac_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ switch (val.type)
+ {
+ case BCMBAL_TM_BAC_TYPE_TAILDROP:
+ cli_parm = bcmcli_find_named_parm(session, "bac.max_size");
+ if (cli_parm != NULL)
+ {
+ val.u.taildrop.max_size = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.max_size is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_RED:
+ cli_parm = bcmcli_find_parm_by_prefix(session, "bac.red.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "bac.red.min_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.red.red.min_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red.min_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.red.max_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.red.red.max_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red.max_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.red.max_probability");
+ if (cli_parm != NULL)
+ {
+ val.u.red.red.max_probability = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red.max_probability is not set\n");
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WRED:
+ cli_parm = bcmcli_find_parm_by_prefix(session, "bac.green.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "bac.green.min_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.green.min_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.green.min_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.green.max_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.green.max_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.green.max_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.green.max_probability");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.green.max_probability = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.green.max_probability is not set\n");
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.green is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "bac.yellow.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "bac.yellow.min_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.yellow.min_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.yellow.min_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.yellow.max_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.yellow.max_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.yellow.max_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.yellow.max_probability");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.yellow.max_probability = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.yellow.max_probability is not set\n");
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.yellow is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "bac.red.");
+ if (cli_parm != NULL)
+ {
+ cli_parm = bcmcli_find_named_parm(session, "bac.red.min_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.red.min_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red.min_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.red.max_threshold");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.red.max_threshold = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red.max_threshold is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bac.red.max_probability");
+ if (cli_parm != NULL)
+ {
+ val.u.wred.red.max_probability = (bcmbal_percent) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red.max_probability is not set\n");
+ return BCM_ERR_PARM;
+ }
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "bac.red is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ default:
+ bcmbal_apicli_print_complete(session, BCM_ERR_RANGE, "\n");
+ return BCM_ERR_RANGE;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, tm_queue, bac, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_bac val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_QUEUE_CFG_ID_BAC, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_queue, bac, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_queue_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_queue_cfg cfg; /**< declare main API struct */
+ bcmbal_tm_queue_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_tm_queue_cfg cfg;\n");
+ bcmcli_log("bcmbal_tm_queue_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sched_id");
+ if (cli_parm != NULL)
+ {
+ key.sched_id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID, &key.sched_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "sched_dir");
+ if (cli_parm != NULL)
+ {
+ key.sched_dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR, &key.sched_dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_queue_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, tm_queue, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, tm_queue, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_queue_stat_get(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_queue_stat stat; /**< declare main API struct */
+ bcmbal_tm_queue_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_tm_queue_stat stat;\n");
+ bcmcli_log("bcmbal_tm_queue_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_stat_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "sched_id");
+ if (cli_parm != NULL)
+ {
+ key.sched_id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID, &key.sched_id);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "sched_dir");
+ if (cli_parm != NULL)
+ {
+ key.sched_dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "sched_dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.sched_dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR, &key.sched_dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_queue_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_QUEUE_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_STAT_INIT(&stat, tm_queue, key);
+ bcmcli_log("BCMBAL_STAT_INIT(&stat, tm_queue, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "packets_ok");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, tm_queue, packets_ok);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, tm_queue, packets_ok);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bytes_ok");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, tm_queue, bytes_ok);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, tm_queue, bytes_ok);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "packets_discarded");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, tm_queue, packets_discarded);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, tm_queue, packets_discarded);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "bytes_discarded");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_STAT_PROP_GET(&stat, tm_queue, bytes_discarded);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, tm_queue, bytes_discarded);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_STAT_PROP_IS_SET(&stat, tm_queue, packets_ok) && !BCMBAL_STAT_PROP_IS_SET(&stat, tm_queue, bytes_ok) && !BCMBAL_STAT_PROP_IS_SET(&stat, tm_queue, packets_discarded) && !BCMBAL_STAT_PROP_IS_SET(&stat, tm_queue, bytes_discarded))
+ {
+ BCMBAL_STAT_PROP_GET(&stat, tm_queue, all_properties);
+ bcmcli_log("BCMBAL_STAT_PROP_GET(&stat, tm_queue, all_properties);\n");
+ }
+
+ /* call API */
+ err = bcmbal_stat_get(&stat.hdr);
+ bcmcli_log("bcmbal_stat_get(&stat.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &stat.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_sched_cfg_get(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_sched_cfg cfg; /**< declare main API struct */
+ bcmbal_tm_sched_key key = { }; /**< declare key */
+ uint8_t *list_mem; /**< declare memory buffer for variable-sized lists */
+ bcmcli_log("bcmbal_tm_sched_cfg cfg;\n");
+ bcmcli_log("bcmbal_tm_sched_key key = { };\n");
+ bcmcli_log("uint8_t* list_mem;\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_get");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "dir");
+ if (cli_parm != NULL)
+ {
+ key.dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_SCHED_KEY_ID_DIR, &key.dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_SCHED_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, tm_sched, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, tm_sched, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_named_parm(session, "owner");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, owner);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, owner);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_type");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sched_type);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sched_type);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_parent");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sched_parent);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sched_parent);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_child_type");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sched_child_type);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sched_child_type);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rate");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, rate);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, rate);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tcont_sla");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, tcont_sla);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, tcont_sla);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "creation_mode");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, creation_mode);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, creation_mode);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "queues");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, queues);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, queues);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sub_scheds");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sub_scheds);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, sub_scheds);\n");
+ }
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "num_priorities");
+ if (cli_parm != NULL)
+ {
+ if (cli_parm->value.number)
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, num_priorities);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, num_priorities);\n");
+ }
+ }
+
+ /* if no properties were requested, include everything */
+ if (!BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, owner) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, sched_type) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, sched_parent) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, sched_child_type) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, rate) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, tcont_sla) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, creation_mode) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, queues) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, sub_scheds) && !BCMBAL_CFG_PROP_IS_SET(&cfg, tm_sched, num_priorities))
+ {
+ BCMBAL_CFG_PROP_GET(&cfg, tm_sched, all_properties);
+ bcmcli_log("BCMBAL_CFG_PROP_GET(&cfg, tm_sched, all_properties);\n");
+ }
+
+ /* set memory to use for variable-sized lists */
+ list_mem = bcmbal_apicli_byte_pool_calloc(byte_pool, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ if (list_mem == NULL)
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_NOMEM, "\n");
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmcli_log("list_mem = bcmos_calloc(BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+ BCMBAL_CFG_LIST_BUF_SET(&cfg, tm_sched, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);
+ bcmcli_log("BCMBAL_CFG_LIST_BUF_SET(&cfg, tm_sched, list_mem, BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE);\n");
+
+ /* call API */
+ err = bcmbal_cfg_get(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_get(&cfg.hdr);\n");
+ if (err == BCM_ERR_OK)
+ {
+ /* print API contents to the CLI */
+ bcmbal_apicli_print_data_start(session);
+ err = bcmbal_apicli_msg_dump(session, &cfg.hdr.hdr);
+ }
+
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_sched_cfg_set(bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_sched_cfg cfg; /**< declare main API struct */
+ bcmbal_tm_sched_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_tm_sched_cfg cfg;\n");
+ bcmcli_log("bcmbal_tm_sched_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_set");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "dir");
+ if (cli_parm != NULL)
+ {
+ key.dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_SCHED_KEY_ID_DIR, &key.dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_SCHED_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, tm_sched, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, tm_sched, key);\n");
+
+ /* decode API parameters from CLI */
+ cli_parm = bcmcli_find_parm_by_prefix(session, "owner.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_owner val = { };
+ cli_parm = bcmcli_find_named_parm(session, "owner.type");
+ if (cli_parm != NULL)
+ {
+ val.type = (bcmbal_tm_sched_owner_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ switch (val.type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ cli_parm = bcmcli_find_named_parm(session, "owner.intf_type");
+ if (cli_parm != NULL)
+ {
+ val.u.interface.intf_type = (bcmbal_intf_type) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.intf_type is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner.intf_id");
+ if (cli_parm != NULL)
+ {
+ val.u.interface.intf_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ cli_parm = bcmcli_find_named_parm(session, "owner.intf_id");
+ if (cli_parm != NULL)
+ {
+ val.u.sub_term.intf_id = (bcmbal_intf_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner.sub_term_id");
+ if (cli_parm != NULL)
+ {
+ val.u.sub_term.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ cli_parm = bcmcli_find_named_parm(session, "owner.intf_id");
+ if (cli_parm != NULL)
+ {
+ val.u.agg_port.intf_id = cli_parm->value.unumber;
+ val.u.agg_port.presence_mask = val.u.agg_port.presence_mask | BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_INTF_ID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner.sub_term_id");
+ if (cli_parm != NULL)
+ {
+ val.u.agg_port.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ val.u.agg_port.presence_mask = val.u.agg_port.presence_mask | BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_SUB_TERM_ID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner.agg_port_id");
+ if (cli_parm != NULL)
+ {
+ val.u.agg_port.agg_port_id = (bcmbal_aggregation_port_id) cli_parm->value.unumber;
+ val.u.agg_port.presence_mask = val.u.agg_port.presence_mask | BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_AGG_PORT_ID;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ cli_parm = bcmcli_find_named_parm(session, "owner.intf_id");
+ if (cli_parm != NULL)
+ {
+ val.u.uni.intf_id = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.intf_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner.sub_term_id");
+ if (cli_parm != NULL)
+ {
+ val.u.uni.sub_term_id = (bcmbal_sub_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.sub_term_id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "owner.idx");
+ if (cli_parm != NULL)
+ {
+ val.u.uni.idx = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.idx is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ cli_parm = bcmcli_find_named_parm(session, "owner.idx");
+ if (cli_parm != NULL)
+ {
+ val.u.virtual.idx = cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "owner.idx is not set\n");
+ return BCM_ERR_PARM;
+ }
+ break;
+ default:
+ bcmbal_apicli_print_complete(session, BCM_ERR_RANGE, "\n");
+ return BCM_ERR_RANGE;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_sched_owner val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_OWNER, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, owner, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_type");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_type val;
+ val = (bcmbal_tm_sched_type) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_type, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_type, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "sched_parent.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_parent val = { };
+ cli_parm = bcmcli_find_named_parm(session, "sched_parent.sched_id");
+ if (cli_parm != NULL)
+ {
+ val.sched_id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SCHED_PARENT_ID_SCHED_ID;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_parent.priority");
+ if (cli_parm != NULL)
+ {
+ val.priority = (bcmbal_tm_priority) cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SCHED_PARENT_ID_PRIORITY;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_parent.weight");
+ if (cli_parm != NULL)
+ {
+ val.weight = (bcmbal_tm_weight) cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SCHED_PARENT_ID_WEIGHT;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_parent, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_sched_parent val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_parent, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "sched_child_type");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_sched_child_type val;
+ val = (bcmbal_tm_sched_child_type) cli_parm->value.enum_val;
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_child_type, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, sched_child_type, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE, &val);
+ bcmcli_log(");\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "rate.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_shaping val = { };
+ cli_parm = bcmcli_find_named_parm(session, "rate.sbr");
+ if (cli_parm != NULL)
+ {
+ val.sbr = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SHAPING_ID_SBR;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rate.pbr");
+ if (cli_parm != NULL)
+ {
+ val.pbr = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SHAPING_ID_PBR;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "rate.burst");
+ if (cli_parm != NULL)
+ {
+ val.burst = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_SHAPING_ID_BURST;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, rate, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_shaping val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_RATE, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, rate, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_parm_by_prefix(session, "tcont_sla.");
+ if (cli_parm != NULL)
+ {
+ bcmbal_tm_tcont_sla val = { };
+ cli_parm = bcmcli_find_named_parm(session, "tcont_sla.extra_bw_elig");
+ if (cli_parm != NULL)
+ {
+ val.extra_bw_elig = (bcmbal_extra_bw_eligibility_type) cli_parm->value.enum_val;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_TCONT_SLA_ID_EXTRA_BW_ELIG;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tcont_sla.nrt_cbr");
+ if (cli_parm != NULL)
+ {
+ val.nrt_cbr = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_TCONT_SLA_ID_NRT_CBR;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tcont_sla.rt_cbr");
+ if (cli_parm != NULL)
+ {
+ val.rt_cbr = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_TCONT_SLA_ID_RT_CBR;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tcont_sla.rt_profile");
+ if (cli_parm != NULL)
+ {
+ val.rt_profile = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_TCONT_SLA_ID_RT_PROFILE;
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "tcont_sla.nrt_profile");
+ if (cli_parm != NULL)
+ {
+ val.nrt_profile = cli_parm->value.unumber;
+ val.presence_mask = val.presence_mask | BCMBAL_TM_TCONT_SLA_ID_NRT_PROFILE;
+ }
+
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, tcont_sla, val);
+ bcmcli_log("{\n");
+ bcmcli_log("bcmbal_tm_tcont_sla val = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA, &val);
+ bcmcli_log(";\n");
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, tcont_sla, val);\n");
+ bcmcli_log("}\n");
+ }
+
+ cli_parm = bcmcli_find_named_parm(session, "num_priorities");
+ if (cli_parm != NULL)
+ {
+ uint8_t val;
+ val = cli_parm->value.unumber;
+ BCMBAL_CFG_PROP_SET(&cfg, tm_sched, num_priorities, val);
+ bcmcli_log("BCMBAL_CFG_PROP_SET(&cfg, tm_sched, num_priorities, ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES, &val);
+ bcmcli_log(");\n");
+ }
+
+ /* call API */
+ err = bcmbal_cfg_set(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_set(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_cli_tm_sched_cfg_clear(bcmcli_session *session)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmos_errno err;
+ bcmbal_tm_sched_cfg cfg; /**< declare main API struct */
+ bcmbal_tm_sched_key key = { }; /**< declare key */
+ bcmcli_log("bcmbal_tm_sched_cfg cfg;\n");
+ bcmcli_log("bcmbal_tm_sched_key key = { };\n");
+ bcmbal_apicli_print_start(session, "bcmbal_cfg_clear");
+
+ /* build key from CLI parameters */
+ cli_parm = bcmcli_find_named_parm(session, "dir");
+ if (cli_parm != NULL)
+ {
+ key.dir = (bcmbal_tm_sched_dir) cli_parm->value.enum_val;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "dir is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.dir = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_SCHED_KEY_ID_DIR, &key.dir);
+ bcmcli_log(";\n");
+ cli_parm = bcmcli_find_named_parm(session, "id");
+ if (cli_parm != NULL)
+ {
+ key.id = (bcmbal_tm_sched_id) cli_parm->value.unumber;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "id is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ bcmcli_log("key.id = ");
+ bcmbal_apicli_log_prop_val(BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, BCMBAL_TM_SCHED_KEY_ID_ID, &key.id);
+ bcmcli_log(";\n");
+
+ /* init the API struct */
+ BCMBAL_CFG_INIT(&cfg, tm_sched, key);
+ bcmcli_log("BCMBAL_CFG_INIT(&cfg, tm_sched, key);\n");
+
+ /* call API */
+ err = bcmbal_cfg_clear(&cfg.hdr);
+ bcmcli_log("bcmbal_cfg_clear(&cfg.hdr);\n");
+ bcmbal_apicli_print_complete(session, err, NULL);
+ return err;
+}
+
+/******************************************************************************/
+static bcmos_errno bcmbal_apicli_root(bcmbal_mgt_group group_type, bcmbal_obj_msg_type msg_type, bcmcli_session *session, bcmbal_apicli_byte_pool *byte_pool)
+{
+ bcmcli_cmd_parm *cli_parm;
+ bcmbal_obj_id obj_id;
+ cli_parm = bcmcli_find_named_parm(session, "object");
+ if (cli_parm != NULL)
+ {
+ obj_id = cli_parm->value.number;
+ }
+ else
+ {
+ bcmbal_apicli_print_complete(session, BCM_ERR_PARM, "object is not set\n");
+ return BCM_ERR_PARM;
+ }
+
+ switch (obj_id)
+ {
+ case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_access_terminal_cfg_get(session);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_access_terminal_cfg_set(session);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_access_terminal_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_FLOW:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_flow_cfg_get(session);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_flow_cfg_set(session);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_flow_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ return bcmbal_cli_flow_stat_get(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_GROUP:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_group_cfg_get(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_group_cfg_set(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_group_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_INTERFACE:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_interface_cfg_get(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_interface_cfg_set(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_interface_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ return bcmbal_cli_interface_stat_get(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_PACKET:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_packet_cfg_get(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_packet_cfg_set(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_packet_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_subscriber_terminal_cfg_get(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_subscriber_terminal_cfg_set(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_subscriber_terminal_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ return bcmbal_cli_subscriber_terminal_stat_get(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_TM_QUEUE:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_tm_queue_cfg_get(session);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_tm_queue_cfg_set(session);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_tm_queue_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ return bcmbal_cli_tm_queue_stat_get(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_TM_SCHED:
+ switch (group_type)
+ {
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (msg_type)
+ {
+ case BCMBAL_OBJ_MSG_TYPE_GET:
+ return bcmbal_cli_tm_sched_cfg_get(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_SET:
+ return bcmbal_cli_tm_sched_cfg_set(session, byte_pool);
+ case BCMBAL_OBJ_MSG_TYPE_CLEAR:
+ return bcmbal_cli_tm_sched_cfg_clear(session);
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+}
+
+/* Perform an API call based on CLI input */
+bcmos_errno bcmbal_apicli_call(bcmbal_mgt_group group_type, bcmbal_obj_msg_type msg_type, bcmcli_session *session)
+{
+ bcmos_errno err;
+ bcmbal_apicli_byte_pool byte_pool;
+
+ /* setup memory pool for dynamically-sized list memory allocation */
+ err = bcmbal_apicli_byte_pool_create(&byte_pool);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ /* call the root API handler */
+ err = bcmbal_apicli_root(group_type, msg_type, session, &byte_pool);
+
+ /* free all dynamically allocated memory */
+ bcmbal_apicli_byte_pool_destroy(&byte_pool);
+
+ return err;
+}
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli_handlers.h b/bal_release/src/lib/libbalapicli/bal_api_cli_handlers.h
new file mode 100644
index 0000000..dc7f1fc
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli_handlers.h
@@ -0,0 +1,46 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(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 BCMBAL_APICLI_HANDLERS_H_
+#define BCMBAL_APICLI_HANDLERS_H_
+
+#include <bcmos_system.h>
+#include <bal_api.h>
+#include <bcmcli.h>
+
+/* the maximum amount of memory that could possibly by used by all variable-sized lists within a GET request */
+#define BCMBAL_APICLI_DYNAMIC_LIST_BUFFER_SIZE (32 * 1024)
+
+/* Perform an API call based on CLI input */
+bcmos_errno bcmbal_apicli_call(
+ bcmbal_mgt_group group_type,
+ bcmbal_obj_msg_type msg_type,
+ bcmcli_session *session);
+
+#endif
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli_helpers.c b/bal_release/src/lib/libbalapicli/bal_api_cli_helpers.c
new file mode 100644
index 0000000..d9b6e43
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli_helpers.c
@@ -0,0 +1,1913 @@
+#include <bcmos_system.h>
+#include <bcmcli.h>
+#include <bal_api.h>
+#include "bal_api_cli_helpers.h"
+
+/* allow possibly unused descriptors to make the code easier to generate */
+#ifdef __GNUC__
+#define BCM_DESCR __attribute__((unused))
+#else
+#define BCM_DESCR
+#endif
+
+/* Unless specified in the XML model, dynamic arrays will have this max size (in bytes, will divide by element size) */
+#define DEFAULT_DYN_ARR_MAX_SIZE 2048
+
+/* ==== Base Type Descriptors ==== */
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint8_t = { .name = "uint8", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM, .size = sizeof(uint8_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint16_t = { .name = "uint16", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM, .size = sizeof(uint16_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint32_t = { .name = "uint32", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM, .size = sizeof(uint32_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint64_t = { .name = "uint64", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM, .size = sizeof(uint64_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint8_t_hex = { .name = "uint8_hex", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX, .size = sizeof(uint8_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint16_t_hex = { .name = "uint16_hex", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX, .size = sizeof(uint16_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint32_t_hex = { .name = "uint32_hex", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX, .size = sizeof(uint32_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint64_t_hex = { .name = "uint64_hex", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX, .size = sizeof(uint64_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_int8_t = { .name = "int8", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_SNUM, .size = sizeof(int8_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_int16_t = { .name = "int16", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_SNUM, .size = sizeof(int16_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_int32_t = { .name = "int32", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_SNUM, .size = sizeof(int32_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_int64_t = { .name = "int64", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_SNUM, .size = sizeof(int64_t) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_float = { .name = "float", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_FLOAT, .size = sizeof(float) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_double = { .name = "double", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_FLOAT, .size = sizeof(double) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmos_mac_address = { .name = "mac", .descr = "MAC address", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_MAC, .size = sizeof(bcmos_mac_address) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmos_ipv4_address = { .name = "ipv4", .descr = "IPv4 address", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_IPV4, .size = sizeof(bcmos_ipv4_address) };
+
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmos_bool = { .name = "bool", .descr = "Boolean", .base_type = BCMBAL_APICLI_BASE_TYPE_ID_BOOL, .size = sizeof(bcmos_bool) };
+
+/* ==== Object Type Information ==== */
+static char *object_name[] = { "access_terminal", "flow", "group", "interface", "packet", "subscriber_terminal", "tm_queue", "tm_sched" };
+static char *object_descr[] = { "BAL Access Terminal Object", "BAL Flow", "BAL Group", "BAL interface object", "Packet that can be transmitted or received", "BAL Subscriber Terminal", "Transmit queue", "Scheduling node" };
+
+/* ==== Supporting Types ==== */
+bcmcli_enum_val bcmbal_access_terminal_cfg_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS }, { .name = "iwf_mode", .val = BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_access_terminal_cfg_id = { .name = "bcmbal_access_terminal_cfg_id", .descr = "Identifiers for all properties contained in the access_terminal_cfg group.", .size = sizeof(bcmbal_access_terminal_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_access_terminal_cfg_id_string_table } };
+bcmcli_enum_val bcmbal_access_terminal_ind_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS }, { .name = "iwf_mode", .val = BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_access_terminal_ind_id = { .name = "bcmbal_access_terminal_ind_id", .descr = "Identifiers for all properties contained in the access_terminal_ind group.", .size = sizeof(bcmbal_access_terminal_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_access_terminal_ind_id_string_table } };
+bcmcli_enum_val bcmbal_access_terminal_key_id_string_table[] = { { .name = "access_term_id", .val = BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_access_terminal_key_id = { .name = "bcmbal_access_terminal_key_id", .descr = "Identifiers for all properties contained in the access_terminal_key group.", .size = sizeof(bcmbal_access_terminal_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_access_terminal_key_id_string_table } };
+bcmcli_enum_val bcmbal_action_id_string_table[] = { { .name = "none", .val = BCMBAL_ACTION_ID_NONE }, { .name = "cmds_bitmask", .val = BCMBAL_ACTION_ID_CMDS_BITMASK }, { .name = "o_vid", .val = BCMBAL_ACTION_ID_O_VID }, { .name = "o_pbits", .val = BCMBAL_ACTION_ID_O_PBITS }, { .name = "o_tpid", .val = BCMBAL_ACTION_ID_O_TPID }, { .name = "i_vid", .val = BCMBAL_ACTION_ID_I_VID }, { .name = "i_pbits", .val = BCMBAL_ACTION_ID_I_PBITS }, { .name = "i_tpid", .val = BCMBAL_ACTION_ID_I_TPID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_action_id = { .name = "bcmbal_action_id", .descr = "action ID", .size = sizeof(bcmbal_action_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_action_id_string_table } };
+bcmcli_enum_val bcmbal_action_cmd_id_string_table[] = { { .name = "none", .val = BCMBAL_ACTION_CMD_ID_NONE }, { .name = "add_outer_tag", .val = BCMBAL_ACTION_CMD_ID_ADD_OUTER_TAG }, { .name = "remove_outer_tag", .val = BCMBAL_ACTION_CMD_ID_REMOVE_OUTER_TAG }, { .name = "xlate_outer_tag", .val = BCMBAL_ACTION_CMD_ID_XLATE_OUTER_TAG }, { .name = "xlate_two_tags", .val = BCMBAL_ACTION_CMD_ID_XLATE_TWO_TAGS }, { .name = "discard_ds_bcast", .val = BCMBAL_ACTION_CMD_ID_DISCARD_DS_BCAST }, { .name = "discard_ds_unknown", .val = BCMBAL_ACTION_CMD_ID_DISCARD_DS_UNKNOWN }, { .name = "add_two_tags", .val = BCMBAL_ACTION_CMD_ID_ADD_TWO_TAGS }, { .name = "remove_two_tags", .val = BCMBAL_ACTION_CMD_ID_REMOVE_TWO_TAGS }, { .name = "remark_pbits", .val = BCMBAL_ACTION_CMD_ID_REMARK_PBITS }, { .name = "copy_pbits", .val = BCMBAL_ACTION_CMD_ID_COPY_PBITS }, { .name = "reverse_copy_pbits", .val = BCMBAL_ACTION_CMD_ID_REVERSE_COPY_PBITS }, { .name = "dscp_to_pbits", .val = BCMBAL_ACTION_CMD_ID_DSCP_TO_PBITS }, { .name = "trap_to_host", .val = BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_action_cmd_id = { .name = "bcmbal_action_cmd_id", .descr = "action_cmd_id", .size = sizeof(bcmbal_action_cmd_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_action_cmd_id_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_action_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_action, presence_mask), .type = &type_descr_bcmbal_action_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "cmds_bitmask", .descr = "Commands bitmask", .offset = offsetof(bcmbal_action, cmds_bitmask), .type = &type_descr_bcmbal_action_cmd_id }, { .name = "o_vid", .descr = "Outer vid", .offset = offsetof(bcmbal_action, o_vid), .type = &type_descr_uint16_t }, { .name = "o_pbits", .descr = "Outer pbits", .offset = offsetof(bcmbal_action, o_pbits), .type = &type_descr_uint8_t }, { .name = "o_tpid", .descr = "Outer tpid", .offset = offsetof(bcmbal_action, o_tpid), .type = &type_descr_uint16_t }, { .name = "i_vid", .descr = "Inner vid", .offset = offsetof(bcmbal_action, i_vid), .type = &type_descr_uint16_t }, { .name = "i_pbits", .descr = "Inner pbits", .offset = offsetof(bcmbal_action, i_pbits), .type = &type_descr_uint8_t }, { .name = "i_tpid", .descr = "Inner tpid", .offset = offsetof(bcmbal_action, i_tpid), .type = &type_descr_uint16_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_action = { .name = "bcmbal_action", .descr = "action", .size = sizeof(bcmbal_action), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_action_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_action_fields } } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_aggregation_port_id_list_u8 = { .name = "bcmbal_aggregation_port_id_list_u8", .descr = "Variable-length list of aggregation_port_id", .size = sizeof(bcmbal_aggregation_port_id_list_u8), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint16_t, .len_size = 1, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_aggregation_port_id) } } };
+bcmcli_enum_val bcmbal_classifier_id_string_table[] = { { .name = "none", .val = BCMBAL_CLASSIFIER_ID_NONE }, { .name = "o_tpid", .val = BCMBAL_CLASSIFIER_ID_O_TPID }, { .name = "o_vid", .val = BCMBAL_CLASSIFIER_ID_O_VID }, { .name = "i_tpid", .val = BCMBAL_CLASSIFIER_ID_I_TPID }, { .name = "i_vid", .val = BCMBAL_CLASSIFIER_ID_I_VID }, { .name = "o_pbits", .val = BCMBAL_CLASSIFIER_ID_O_PBITS }, { .name = "i_pbits", .val = BCMBAL_CLASSIFIER_ID_I_PBITS }, { .name = "ether_type", .val = BCMBAL_CLASSIFIER_ID_ETHER_TYPE }, { .name = "dst_mac", .val = BCMBAL_CLASSIFIER_ID_DST_MAC }, { .name = "src_mac", .val = BCMBAL_CLASSIFIER_ID_SRC_MAC }, { .name = "ip_proto", .val = BCMBAL_CLASSIFIER_ID_IP_PROTO }, { .name = "dst_ip", .val = BCMBAL_CLASSIFIER_ID_DST_IP }, { .name = "src_ip", .val = BCMBAL_CLASSIFIER_ID_SRC_IP }, { .name = "src_port", .val = BCMBAL_CLASSIFIER_ID_SRC_PORT }, { .name = "dst_port", .val = BCMBAL_CLASSIFIER_ID_DST_PORT }, { .name = "pkt_tag_type", .val = BCMBAL_CLASSIFIER_ID_PKT_TAG_TYPE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_classifier_id = { .name = "bcmbal_classifier_id", .descr = "classifier ID", .size = sizeof(bcmbal_classifier_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_classifier_id_string_table } };
+bcmcli_enum_val bcmbal_pkt_tag_type_string_table[] = { { .name = "none", .val = BCMBAL_PKT_TAG_TYPE_NONE }, { .name = "untagged", .val = BCMBAL_PKT_TAG_TYPE_UNTAGGED }, { .name = "single_tag", .val = BCMBAL_PKT_TAG_TYPE_SINGLE_TAG }, { .name = "double_tag", .val = BCMBAL_PKT_TAG_TYPE_DOUBLE_TAG }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_pkt_tag_type = { .name = "bcmbal_pkt_tag_type", .descr = "Packet tag type", .size = sizeof(bcmbal_pkt_tag_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_pkt_tag_type_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_classifier_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_classifier, presence_mask), .type = &type_descr_bcmbal_classifier_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "o_tpid", .descr = "Outer TPID of the packet to be classified", .offset = offsetof(bcmbal_classifier, o_tpid), .type = &type_descr_uint16_t }, { .name = "o_vid", .descr = "Outer VID of the packet to be classified", .offset = offsetof(bcmbal_classifier, o_vid), .type = &type_descr_uint16_t }, { .name = "i_tpid", .descr = "Inner TPID of the packet to be classified", .offset = offsetof(bcmbal_classifier, i_tpid), .type = &type_descr_uint16_t }, { .name = "i_vid", .descr = "Inner VID of the packet to be classified", .offset = offsetof(bcmbal_classifier, i_vid), .type = &type_descr_uint16_t }, { .name = "o_pbits", .descr = "Outer PBITS of the packet to be classified", .offset = offsetof(bcmbal_classifier, o_pbits), .type = &type_descr_uint8_t }, { .name = "i_pbits", .descr = "Inner PBITS of the packet to be classified", .offset = offsetof(bcmbal_classifier, i_pbits), .type = &type_descr_uint8_t }, { .name = "ether_type", .descr = "Ethertype of the packet to be classified", .offset = offsetof(bcmbal_classifier, ether_type), .type = &type_descr_uint16_t }, { .name = "dst_mac", .descr = "Destination MAC address of the packet to be classified", .offset = offsetof(bcmbal_classifier, dst_mac), .type = &type_descr_bcmos_mac_address }, { .name = "src_mac", .descr = "Source MAC address of the packet to be classified", .offset = offsetof(bcmbal_classifier, src_mac), .type = &type_descr_bcmos_mac_address }, { .name = "ip_proto", .descr = "IP protocol of the packet to be classified", .offset = offsetof(bcmbal_classifier, ip_proto), .type = &type_descr_uint8_t }, { .name = "dst_ip", .descr = "Destination IP address of the packet to be classified", .offset = offsetof(bcmbal_classifier, dst_ip), .type = &type_descr_bcmos_ipv4_address }, { .name = "src_ip", .descr = "Source IP address of the packet to be classified", .offset = offsetof(bcmbal_classifier, src_ip), .type = &type_descr_bcmos_ipv4_address }, { .name = "src_port", .descr = "Source port of the packet to be classified", .offset = offsetof(bcmbal_classifier, src_port), .type = &type_descr_uint16_t }, { .name = "dst_port", .descr = "Destination port of the packet to be classified", .offset = offsetof(bcmbal_classifier, dst_port), .type = &type_descr_uint16_t }, { .name = "pkt_tag_type", .descr = "The tag type of the ingress packets", .offset = offsetof(bcmbal_classifier, pkt_tag_type), .type = &type_descr_bcmbal_pkt_tag_type } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_classifier = { .name = "bcmbal_classifier", .descr = "classifier", .size = sizeof(bcmbal_classifier), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_classifier_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_classifier_fields } } };
+bcmcli_enum_val bcmbal_control_string_table[] = { { .name = "disable", .val = BCMBAL_CONTROL_DISABLE }, { .name = "enable", .val = BCMBAL_CONTROL_ENABLE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_control = { .name = "bcmbal_control", .descr = "Generic enable/disable enumeration", .size = sizeof(bcmbal_control), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_control_string_table } };
+bcmcli_enum_val bcmbal_dest_type_string_table[] = { { .name = "nni", .val = BCMBAL_DEST_TYPE_NNI }, { .name = "sub_term", .val = BCMBAL_DEST_TYPE_SUB_TERM }, { .name = "host", .val = BCMBAL_DEST_TYPE_HOST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_dest_type = { .name = "bcmbal_dest_type", .descr = "Destination type", .size = sizeof(bcmbal_dest_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_dest_type_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_dest_fields[] = { { .name = "type", .descr = "packet destination", .offset = offsetof(bcmbal_dest, type), .type = &type_descr_bcmbal_dest_type } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_dest_nni_fields[] = { { .name = "int_id", .descr = "Interface ID", .offset = offsetof(bcmbal_dest, u.nni.int_id) - offsetof(bcmbal_dest, u.nni.int_id), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_dest_nni = { .name = "bcmbal_dest_nni", .descr = "Packet destination nni", .size = sizeof(((bcmbal_dest *)0)->u.nni), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_dest_nni_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_dest_nni_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_dest_sub_term_fields[] = { { .name = "sub_term_id", .descr = "Subscriber terminal ID", .offset = offsetof(bcmbal_dest, u.sub_term.sub_term_id) - offsetof(bcmbal_dest, u.sub_term.sub_term_id), .type = &type_descr_uint32_t }, { .name = "sub_term_uni", .descr = "Subscriber terminal UNI", .offset = offsetof(bcmbal_dest, u.sub_term.sub_term_uni) - offsetof(bcmbal_dest, u.sub_term.sub_term_id), .type = &type_descr_uint16_t }, { .name = "int_id", .descr = "Interface ID", .offset = offsetof(bcmbal_dest, u.sub_term.int_id) - offsetof(bcmbal_dest, u.sub_term.sub_term_id), .type = &type_descr_uint16_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_dest_sub_term = { .name = "bcmbal_dest_sub_term", .descr = "Packet destination subscriber terminal", .size = sizeof(((bcmbal_dest *)0)->u.sub_term), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_dest_sub_term_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_dest_sub_term_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_dest_union_fields[] = { { .name = "u.nni", .descr = "", .offset = offsetof(bcmbal_dest, u.nni), .type = &type_descr_bcmbal_dest_nni }, { .name = "u.sub_term", .descr = "", .offset = offsetof(bcmbal_dest, u.sub_term), .type = &type_descr_bcmbal_dest_sub_term }, { }, { } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_dest = { .name = "bcmbal_dest", .descr = "Packet destination", .size = sizeof(bcmbal_dest), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNION, .x = { .u = { .num_common_fields = sizeof(type_descr_bcmbal_dest_fields) / sizeof(bcmbal_apicli_field_descr), .common_fields = type_descr_bcmbal_dest_fields, .classifier_idx = 0, .union_fields = type_descr_bcmbal_dest_union_fields } } };
+bcmcli_enum_val bcmbal_ds_miss_mode_string_table[] = { { .name = "discard", .val = BCMBAL_DS_MISS_MODE_DISCARD }, { .name = "broadcast", .val = BCMBAL_DS_MISS_MODE_BROADCAST }, { .name = "vid", .val = BCMBAL_DS_MISS_MODE_VID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_ds_miss_mode = { .name = "bcmbal_ds_miss_mode", .descr = "Downstrean action for unknown packets", .size = sizeof(bcmbal_ds_miss_mode), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_ds_miss_mode_string_table } };
+bcmcli_enum_val bcmbal_extra_bw_eligibility_type_string_table[] = { { .name = "none", .val = BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NONE }, { .name = "not_assured", .val = BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NOT_ASSURED }, { .name = "best_effort", .val = BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_BEST_EFFORT }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_extra_bw_eligibility_type = { .name = "bcmbal_extra_bw_eligibility_type", .descr = "Extra BW Eligibility Type", .size = sizeof(bcmbal_extra_bw_eligibility_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_extra_bw_eligibility_type_string_table } };
+bcmcli_enum_val bcmbal_flow_cfg_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_FLOW_CFG_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_FLOW_CFG_ID_OPER_STATUS }, { .name = "access_int_id", .val = BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID }, { .name = "network_int_id", .val = BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID }, { .name = "sub_term_id", .val = BCMBAL_FLOW_CFG_ID_SUB_TERM_ID }, { .name = "sub_term_uni_idx", .val = BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX }, { .name = "svc_port_id", .val = BCMBAL_FLOW_CFG_ID_SVC_PORT_ID }, { .name = "agg_port_id", .val = BCMBAL_FLOW_CFG_ID_AGG_PORT_ID }, { .name = "resolve_mac", .val = BCMBAL_FLOW_CFG_ID_RESOLVE_MAC }, { .name = "classifier", .val = BCMBAL_FLOW_CFG_ID_CLASSIFIER }, { .name = "action", .val = BCMBAL_FLOW_CFG_ID_ACTION }, { .name = "sla", .val = BCMBAL_FLOW_CFG_ID_SLA }, { .name = "cookie", .val = BCMBAL_FLOW_CFG_ID_COOKIE }, { .name = "priority", .val = BCMBAL_FLOW_CFG_ID_PRIORITY }, { .name = "group_id", .val = BCMBAL_FLOW_CFG_ID_GROUP_ID }, { .name = "queue", .val = BCMBAL_FLOW_CFG_ID_QUEUE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_cfg_id = { .name = "bcmbal_flow_cfg_id", .descr = "Identifiers for all properties contained in the flow_cfg group.", .size = sizeof(bcmbal_flow_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_flow_cfg_id_string_table } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_id_list_u32 = { .name = "bcmbal_flow_id_list_u32", .descr = "Variable-length list of flow_id", .size = sizeof(bcmbal_flow_id_list_u32), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint32_t, .len_size = 4, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_flow_id) } } };
+bcmcli_enum_val bcmbal_flow_ind_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_FLOW_IND_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_FLOW_IND_ID_OPER_STATUS }, { .name = "access_int_id", .val = BCMBAL_FLOW_IND_ID_ACCESS_INT_ID }, { .name = "network_int_id", .val = BCMBAL_FLOW_IND_ID_NETWORK_INT_ID }, { .name = "sub_term_id", .val = BCMBAL_FLOW_IND_ID_SUB_TERM_ID }, { .name = "svc_port_id", .val = BCMBAL_FLOW_IND_ID_SVC_PORT_ID }, { .name = "agg_port_id", .val = BCMBAL_FLOW_IND_ID_AGG_PORT_ID }, { .name = "resolve_mac", .val = BCMBAL_FLOW_IND_ID_RESOLVE_MAC }, { .name = "base_tc_id", .val = BCMBAL_FLOW_IND_ID_BASE_TC_ID }, { .name = "classifier", .val = BCMBAL_FLOW_IND_ID_CLASSIFIER }, { .name = "action", .val = BCMBAL_FLOW_IND_ID_ACTION }, { .name = "sla", .val = BCMBAL_FLOW_IND_ID_SLA }, { .name = "cookie", .val = BCMBAL_FLOW_IND_ID_COOKIE }, { .name = "priority", .val = BCMBAL_FLOW_IND_ID_PRIORITY }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_ind_id = { .name = "bcmbal_flow_ind_id", .descr = "Identifiers for all properties contained in the flow_ind group.", .size = sizeof(bcmbal_flow_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_flow_ind_id_string_table } };
+bcmcli_enum_val bcmbal_flow_key_id_string_table[] = { { .name = "flow_id", .val = BCMBAL_FLOW_KEY_ID_FLOW_ID }, { .name = "flow_type", .val = BCMBAL_FLOW_KEY_ID_FLOW_TYPE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_key_id = { .name = "bcmbal_flow_key_id", .descr = "Identifiers for all properties contained in the flow_key group.", .size = sizeof(bcmbal_flow_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_flow_key_id_string_table } };
+bcmcli_enum_val bcmbal_flow_stat_id_string_table[] = { { .name = "rx_packets", .val = BCMBAL_FLOW_STAT_ID_RX_PACKETS }, { .name = "rx_bytes", .val = BCMBAL_FLOW_STAT_ID_RX_BYTES }, { .name = "tx_packets", .val = BCMBAL_FLOW_STAT_ID_TX_PACKETS }, { .name = "tx_bytes", .val = BCMBAL_FLOW_STAT_ID_TX_BYTES }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_stat_id = { .name = "bcmbal_flow_stat_id", .descr = "Identifiers for all properties contained in the flow_stat group.", .size = sizeof(bcmbal_flow_stat_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_flow_stat_id_string_table } };
+bcmcli_enum_val bcmbal_flow_type_string_table[] = { { .name = "upstream", .val = BCMBAL_FLOW_TYPE_UPSTREAM }, { .name = "downstream", .val = BCMBAL_FLOW_TYPE_DOWNSTREAM }, { .name = "broadcast", .val = BCMBAL_FLOW_TYPE_BROADCAST }, { .name = "multicast", .val = BCMBAL_FLOW_TYPE_MULTICAST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_type = { .name = "bcmbal_flow_type", .descr = "Flow Type", .size = sizeof(bcmbal_flow_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_flow_type_string_table } };
+bcmcli_enum_val bcmbal_group_cfg_id_string_table[] = { { .name = "members_cmd", .val = BCMBAL_GROUP_CFG_ID_MEMBERS_CMD }, { .name = "members", .val = BCMBAL_GROUP_CFG_ID_MEMBERS }, { .name = "cookie", .val = BCMBAL_GROUP_CFG_ID_COOKIE }, { .name = "flows", .val = BCMBAL_GROUP_CFG_ID_FLOWS }, { .name = "owner", .val = BCMBAL_GROUP_CFG_ID_OWNER }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_cfg_id = { .name = "bcmbal_group_cfg_id", .descr = "Identifiers for all properties contained in the group_cfg group.", .size = sizeof(bcmbal_group_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_group_cfg_id_string_table } };
+bcmcli_enum_val bcmbal_group_key_id_string_table[] = { { .name = "group_id", .val = BCMBAL_GROUP_KEY_ID_GROUP_ID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_key_id = { .name = "bcmbal_group_key_id", .descr = "Identifiers for all properties contained in the group_key group.", .size = sizeof(bcmbal_group_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_group_key_id_string_table } };
+bcmcli_enum_val bcmbal_group_member_cmd_string_table[] = { { .name = "add_members", .val = BCMBAL_GROUP_MEMBER_CMD_ADD_MEMBERS }, { .name = "rem_members", .val = BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS }, { .name = "set_members", .val = BCMBAL_GROUP_MEMBER_CMD_SET_MEMBERS }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_member_cmd = { .name = "bcmbal_group_member_cmd", .descr = "Member operation type", .size = sizeof(bcmbal_group_member_cmd), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_group_member_cmd_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_queue_ref_fields[] = { { .name = "sched_id", .descr = "Scheduler (tm_sched) ID", .offset = offsetof(bcmbal_tm_queue_ref, sched_id), .type = &type_descr_uint32_t }, { .name = "queue_id", .descr = "Queue ID", .offset = offsetof(bcmbal_tm_queue_ref, queue_id), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_ref = { .name = "bcmbal_tm_queue_ref", .descr = "Queue Reference", .size = sizeof(bcmbal_tm_queue_ref), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_queue_ref_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_queue_ref_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_group_member_info_fields[] = { { .name = "intf_id", .descr = "Access interface id for this member", .offset = offsetof(bcmbal_group_member_info, intf_id), .type = &type_descr_uint32_t }, { .name = "svc_port_id", .descr = "The multicast \"GEM\" for this member", .offset = offsetof(bcmbal_group_member_info, svc_port_id), .type = &type_descr_uint16_t }, { .name = "action", .descr = "VLAN actions", .offset = offsetof(bcmbal_group_member_info, action), .type = &type_descr_bcmbal_action }, { .name = "queue", .descr = "Egress queue", .offset = offsetof(bcmbal_group_member_info, queue), .type = &type_descr_bcmbal_tm_queue_ref } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_member_info = { .name = "bcmbal_group_member_info", .descr = "Group Member Info", .size = sizeof(bcmbal_group_member_info), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_group_member_info_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_group_member_info_fields } } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_member_info_list_u16 = { .name = "bcmbal_group_member_info_list_u16", .descr = "Variable-length list of group_member_info", .size = sizeof(bcmbal_group_member_info_list_u16), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_bcmbal_group_member_info, .len_size = 2, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_group_member_info) } } };
+bcmcli_enum_val bcmbal_group_owner_string_table[] = { { .name = "none", .val = BCMBAL_GROUP_OWNER_NONE }, { .name = "multicast", .val = BCMBAL_GROUP_OWNER_MULTICAST }, { .name = "unicast", .val = BCMBAL_GROUP_OWNER_UNICAST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_owner = { .name = "bcmbal_group_owner", .descr = "owner of the group", .size = sizeof(bcmbal_group_owner), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_group_owner_string_table } };
+bcmcli_enum_val bcmbal_interface_cfg_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_INTERFACE_CFG_ID_OPER_STATUS }, { .name = "min_data_agg_port_id", .val = BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID }, { .name = "min_data_svc_port_id", .val = BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID }, { .name = "transceiver_type", .val = BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE }, { .name = "ds_miss_mode", .val = BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE }, { .name = "mtu", .val = BCMBAL_INTERFACE_CFG_ID_MTU }, { .name = "flow_control", .val = BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL }, { .name = "ds_tm", .val = BCMBAL_INTERFACE_CFG_ID_DS_TM }, { .name = "us_tm", .val = BCMBAL_INTERFACE_CFG_ID_US_TM }, { .name = "sub_term_id_list", .val = BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_cfg_id = { .name = "bcmbal_interface_cfg_id", .descr = "Identifiers for all properties contained in the interface_cfg group.", .size = sizeof(bcmbal_interface_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_interface_cfg_id_string_table } };
+bcmcli_enum_val bcmbal_interface_ind_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_INTERFACE_IND_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_INTERFACE_IND_ID_OPER_STATUS }, { .name = "min_data_agg_port_id", .val = BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID }, { .name = "min_data_svc_port_id", .val = BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID }, { .name = "transceiver_type", .val = BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE }, { .name = "ds_miss_mode", .val = BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE }, { .name = "mtu", .val = BCMBAL_INTERFACE_IND_ID_MTU }, { .name = "flow_control", .val = BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL }, { .name = "ds_tm", .val = BCMBAL_INTERFACE_IND_ID_DS_TM }, { .name = "us_tm", .val = BCMBAL_INTERFACE_IND_ID_US_TM }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_ind_id = { .name = "bcmbal_interface_ind_id", .descr = "Identifiers for all properties contained in the interface_ind group.", .size = sizeof(bcmbal_interface_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_interface_ind_id_string_table } };
+bcmcli_enum_val bcmbal_interface_key_id_string_table[] = { { .name = "intf_id", .val = BCMBAL_INTERFACE_KEY_ID_INTF_ID }, { .name = "intf_type", .val = BCMBAL_INTERFACE_KEY_ID_INTF_TYPE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_key_id = { .name = "bcmbal_interface_key_id", .descr = "Identifiers for all properties contained in the interface_key group.", .size = sizeof(bcmbal_interface_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_interface_key_id_string_table } };
+bcmcli_enum_val bcmbal_interface_stat_id_string_table[] = { { .name = "rx_packets", .val = BCMBAL_INTERFACE_STAT_ID_RX_PACKETS }, { .name = "rx_bytes", .val = BCMBAL_INTERFACE_STAT_ID_RX_BYTES }, { .name = "tx_packets", .val = BCMBAL_INTERFACE_STAT_ID_TX_PACKETS }, { .name = "tx_bytes", .val = BCMBAL_INTERFACE_STAT_ID_TX_BYTES }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_stat_id = { .name = "bcmbal_interface_stat_id", .descr = "Identifiers for all properties contained in the interface_stat group.", .size = sizeof(bcmbal_interface_stat_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_interface_stat_id_string_table } };
+bcmcli_enum_val bcmbal_intf_type_string_table[] = { { .name = "nni", .val = BCMBAL_INTF_TYPE_NNI }, { .name = "pon", .val = BCMBAL_INTF_TYPE_PON }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_intf_type = { .name = "bcmbal_intf_type", .descr = "Interface type", .size = sizeof(bcmbal_intf_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_intf_type_string_table } };
+bcmcli_enum_val bcmbal_iwf_mode_string_table[] = { { .name = "direct_mapping", .val = BCMBAL_IWF_MODE_DIRECT_MAPPING }, { .name = "per_flow", .val = BCMBAL_IWF_MODE_PER_FLOW }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_iwf_mode = { .name = "bcmbal_iwf_mode", .descr = "Interworking Function Mode", .size = sizeof(bcmbal_iwf_mode), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_iwf_mode_string_table } };
+bcmcli_enum_val bcmbal_packet_cfg_id_string_table[] = { { .name = "flow_id", .val = BCMBAL_PACKET_CFG_ID_FLOW_ID }, { .name = "flow_type", .val = BCMBAL_PACKET_CFG_ID_FLOW_TYPE }, { .name = "intf_id", .val = BCMBAL_PACKET_CFG_ID_INTF_ID }, { .name = "intf_type", .val = BCMBAL_PACKET_CFG_ID_INTF_TYPE }, { .name = "svc_port", .val = BCMBAL_PACKET_CFG_ID_SVC_PORT }, { .name = "flow_cookie", .val = BCMBAL_PACKET_CFG_ID_FLOW_COOKIE }, { .name = "pkt", .val = BCMBAL_PACKET_CFG_ID_PKT }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_packet_cfg_id = { .name = "bcmbal_packet_cfg_id", .descr = "Identifiers for all properties contained in the packet_cfg group.", .size = sizeof(bcmbal_packet_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_packet_cfg_id_string_table } };
+bcmcli_enum_val bcmbal_packet_ind_id_string_table[] = { { .name = "flow_id", .val = BCMBAL_PACKET_IND_ID_FLOW_ID }, { .name = "flow_type", .val = BCMBAL_PACKET_IND_ID_FLOW_TYPE }, { .name = "intf_id", .val = BCMBAL_PACKET_IND_ID_INTF_ID }, { .name = "intf_type", .val = BCMBAL_PACKET_IND_ID_INTF_TYPE }, { .name = "svc_port", .val = BCMBAL_PACKET_IND_ID_SVC_PORT }, { .name = "flow_cookie", .val = BCMBAL_PACKET_IND_ID_FLOW_COOKIE }, { .name = "pkt", .val = BCMBAL_PACKET_IND_ID_PKT }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_packet_ind_id = { .name = "bcmbal_packet_ind_id", .descr = "Identifiers for all properties contained in the packet_ind group.", .size = sizeof(bcmbal_packet_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_packet_ind_id_string_table } };
+bcmcli_enum_val bcmbal_packet_key_id_string_table[] = { { .name = "reserved", .val = BCMBAL_PACKET_KEY_ID_RESERVED }, { .name = "packet_send_dest", .val = BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_packet_key_id = { .name = "bcmbal_packet_key_id", .descr = "Identifiers for all properties contained in the packet_key group.", .size = sizeof(bcmbal_packet_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_packet_key_id_string_table } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint8_t_arr_10 = { .name = "uint8_t[10]", .descr = "Array of 10 elements of type uint8_t", .size = sizeof(uint8_t[10]), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED, .x = { .arr_fixed = { .elem_type = &type_descr_uint8_t, .size = 10 } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_password_fields[] = { { .name = "arr", .descr = "Array", .offset = offsetof(bcmbal_password, arr), .type = &type_descr_uint8_t_arr_10 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_password = { .name = "bcmbal_password", .descr = "Password", .size = sizeof(bcmbal_password), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_password_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_password_fields } } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint8_t_arr_36 = { .name = "uint8_t[36]", .descr = "Array of 36 elements of type uint8_t", .size = sizeof(uint8_t[36]), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED, .x = { .arr_fixed = { .elem_type = &type_descr_uint8_t, .size = 36 } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_registration_id_fields[] = { { .name = "arr", .descr = "ONU registration ID", .offset = offsetof(bcmbal_registration_id, arr), .type = &type_descr_uint8_t_arr_36 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_registration_id = { .name = "bcmbal_registration_id", .descr = "Registration id", .size = sizeof(bcmbal_registration_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_registration_id_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_registration_id_fields } } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_uint8_t_arr_4 = { .name = "uint8_t[4]", .descr = "Array of 4 elements of type uint8_t", .size = sizeof(uint8_t[4]), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED, .x = { .arr_fixed = { .elem_type = &type_descr_uint8_t, .size = 4 } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_serial_number_fields[] = { { .name = "vendor_id", .descr = "vendor id", .offset = offsetof(bcmbal_serial_number, vendor_id), .type = &type_descr_uint8_t_arr_4 }, { .name = "vendor_specific", .descr = "vendor specific", .offset = offsetof(bcmbal_serial_number, vendor_specific), .type = &type_descr_uint8_t_arr_4 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_serial_number = { .name = "bcmbal_serial_number", .descr = "Serial number", .size = sizeof(bcmbal_serial_number), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_serial_number_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_serial_number_fields } } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_service_port_id_list_u8 = { .name = "bcmbal_service_port_id_list_u8", .descr = "Variable-length list of service_port_id", .size = sizeof(bcmbal_service_port_id_list_u8), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint16_t, .len_size = 1, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_service_port_id) } } };
+bcmcli_enum_val bcmbal_sla_id_string_table[] = { { .name = "none", .val = BCMBAL_SLA_ID_NONE }, { .name = "min_rate", .val = BCMBAL_SLA_ID_MIN_RATE }, { .name = "max_rate", .val = BCMBAL_SLA_ID_MAX_RATE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_sla_id = { .name = "bcmbal_sla_id", .descr = "SLA ID", .size = sizeof(bcmbal_sla_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_sla_id_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_sla_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_sla, presence_mask), .type = &type_descr_bcmbal_sla_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "min_rate", .descr = "The minimal rate for this flow, in kilobits per second (optional)", .offset = offsetof(bcmbal_sla, min_rate), .type = &type_descr_uint32_t }, { .name = "max_rate", .descr = "The maximum rate for this flow, in kilobits per second (optional)", .offset = offsetof(bcmbal_sla, max_rate), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_sla = { .name = "bcmbal_sla", .descr = "SLA", .size = sizeof(bcmbal_sla), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_sla_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_sla_fields } } };
+bcmcli_enum_val bcmbal_state_string_table[] = { { .name = "up", .val = BCMBAL_STATE_UP }, { .name = "down", .val = BCMBAL_STATE_DOWN }, { .name = "testing", .val = BCMBAL_STATE_TESTING }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_state = { .name = "bcmbal_state", .descr = "Admin state values for access terminal object", .size = sizeof(bcmbal_state), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_state_string_table } };
+bcmcli_enum_val bcmbal_status_string_table[] = { { .name = "up", .val = BCMBAL_STATUS_UP }, { .name = "down", .val = BCMBAL_STATUS_DOWN }, { .name = "testing", .val = BCMBAL_STATUS_TESTING }, { .name = "not_present", .val = BCMBAL_STATUS_NOT_PRESENT }, { .name = "lower_layer_down", .val = BCMBAL_STATUS_LOWER_LAYER_DOWN }, { .name = "unknown", .val = BCMBAL_STATUS_UNKNOWN }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_status = { .name = "bcmbal_status", .descr = "Oper status values", .size = sizeof(bcmbal_status), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_status_string_table } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_sub_id_list_u16 = { .name = "bcmbal_sub_id_list_u16", .descr = "Variable-length list of sub_id", .size = sizeof(bcmbal_sub_id_list_u16), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint32_t, .len_size = 2, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_sub_id) } } };
+bcmcli_enum_val bcmbal_subscriber_terminal_cfg_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS }, { .name = "serial_number", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER }, { .name = "password", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD }, { .name = "registration_id", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID }, { .name = "svc_port_id", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID }, { .name = "mac_address", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS }, { .name = "ds_tm", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM }, { .name = "us_tm", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM }, { .name = "svc_port_id_list", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST }, { .name = "agg_port_id_list", .val = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_cfg_id = { .name = "bcmbal_subscriber_terminal_cfg_id", .descr = "Identifiers for all properties contained in the subscriber_terminal_cfg group.", .size = sizeof(bcmbal_subscriber_terminal_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_subscriber_terminal_cfg_id_string_table } };
+bcmcli_enum_val bcmbal_subscriber_terminal_ind_id_string_table[] = { { .name = "admin_state", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE }, { .name = "oper_status", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS }, { .name = "serial_number", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER }, { .name = "password", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD }, { .name = "registration_id", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID }, { .name = "svc_port_id", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID }, { .name = "mac_address", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS }, { .name = "ds_tm", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM }, { .name = "us_tm", .val = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_ind_id = { .name = "bcmbal_subscriber_terminal_ind_id", .descr = "Identifiers for all properties contained in the subscriber_terminal_ind group.", .size = sizeof(bcmbal_subscriber_terminal_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_subscriber_terminal_ind_id_string_table } };
+bcmcli_enum_val bcmbal_subscriber_terminal_key_id_string_table[] = { { .name = "sub_term_id", .val = BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID }, { .name = "intf_id", .val = BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_key_id = { .name = "bcmbal_subscriber_terminal_key_id", .descr = "Identifiers for all properties contained in the subscriber_terminal_key group.", .size = sizeof(bcmbal_subscriber_terminal_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_subscriber_terminal_key_id_string_table } };
+bcmcli_enum_val bcmbal_subscriber_terminal_stat_id_string_table[] = { { .name = "rx_packets", .val = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS }, { .name = "rx_bytes", .val = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES }, { .name = "tx_packets", .val = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS }, { .name = "tx_bytes", .val = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_stat_id = { .name = "bcmbal_subscriber_terminal_stat_id", .descr = "Identifiers for all properties contained in the subscriber_terminal_stat group.", .size = sizeof(bcmbal_subscriber_terminal_stat_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_subscriber_terminal_stat_id_string_table } };
+bcmcli_enum_val bcmbal_tm_bac_type_string_table[] = { { .name = "taildrop", .val = BCMBAL_TM_BAC_TYPE_TAILDROP }, { .name = "wtaildrop", .val = BCMBAL_TM_BAC_TYPE_WTAILDROP }, { .name = "red", .val = BCMBAL_TM_BAC_TYPE_RED }, { .name = "wred", .val = BCMBAL_TM_BAC_TYPE_WRED }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_bac_type = { .name = "bcmbal_tm_bac_type", .descr = "Buffer Admission Control Type", .size = sizeof(bcmbal_tm_bac_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_bac_type_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_red_fields[] = { { .name = "min_threshold", .descr = "Min threshold in percent of max queue size", .offset = offsetof(bcmbal_tm_red, min_threshold), .type = &type_descr_uint8_t }, { .name = "max_threshold", .descr = "Max threshold in percent of max queue size", .offset = offsetof(bcmbal_tm_red, max_threshold), .type = &type_descr_uint8_t }, { .name = "max_probability", .descr = "Discard probability for occupancy between min_threshold and max_threshold", .offset = offsetof(bcmbal_tm_red, max_probability), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_red = { .name = "bcmbal_tm_red", .descr = "Random Early Discard Configuration", .size = sizeof(bcmbal_tm_red), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_red_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_red_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_bac_fields[] = { { .name = "type", .descr = "Buffer Admission Control Type", .offset = offsetof(bcmbal_tm_bac, type), .type = &type_descr_bcmbal_tm_bac_type } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_bac_taildrop_fields[] = { { .name = "max_size", .descr = "max number of packets in the queue", .offset = offsetof(bcmbal_tm_bac, u.taildrop.max_size) - offsetof(bcmbal_tm_bac, u.taildrop.max_size), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_bac_taildrop = { .name = "bcmbal_tm_bac_taildrop", .descr = "tm_bac taildrop", .size = sizeof(((bcmbal_tm_bac *)0)->u.taildrop), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_bac_taildrop_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_bac_taildrop_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_bac_red_fields[] = { { .name = "red", .descr = "Random Early Discard configuration", .offset = offsetof(bcmbal_tm_bac, u.red.red) - offsetof(bcmbal_tm_bac, u.red.red), .type = &type_descr_bcmbal_tm_red } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_bac_red = { .name = "bcmbal_tm_bac_red", .descr = "tm_bac red", .size = sizeof(((bcmbal_tm_bac *)0)->u.red), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_bac_red_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_bac_red_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_bac_wred_fields[] = { { .name = "green", .descr = "Green Random Early Discard Configuration", .offset = offsetof(bcmbal_tm_bac, u.wred.green) - offsetof(bcmbal_tm_bac, u.wred.green), .type = &type_descr_bcmbal_tm_red }, { .name = "yellow", .descr = "Yellow Random Early Discard Configuration", .offset = offsetof(bcmbal_tm_bac, u.wred.yellow) - offsetof(bcmbal_tm_bac, u.wred.green), .type = &type_descr_bcmbal_tm_red }, { .name = "red", .descr = "Red Random Early Discard Configuration", .offset = offsetof(bcmbal_tm_bac, u.wred.red) - offsetof(bcmbal_tm_bac, u.wred.green), .type = &type_descr_bcmbal_tm_red } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_bac_wred = { .name = "bcmbal_tm_bac_wred", .descr = "tm_bac wred", .size = sizeof(((bcmbal_tm_bac *)0)->u.wred), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_bac_wred_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_bac_wred_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_bac_union_fields[] = { { .name = "u.taildrop", .descr = "", .offset = offsetof(bcmbal_tm_bac, u.taildrop), .type = &type_descr_bcmbal_tm_bac_taildrop }, { }, { .name = "u.red", .descr = "", .offset = offsetof(bcmbal_tm_bac, u.red), .type = &type_descr_bcmbal_tm_bac_red }, { .name = "u.wred", .descr = "", .offset = offsetof(bcmbal_tm_bac, u.wred), .type = &type_descr_bcmbal_tm_bac_wred }, { } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_bac = { .name = "bcmbal_tm_bac", .descr = "Queue Buffer Admission Control", .size = sizeof(bcmbal_tm_bac), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNION, .x = { .u = { .num_common_fields = sizeof(type_descr_bcmbal_tm_bac_fields) / sizeof(bcmbal_apicli_field_descr), .common_fields = type_descr_bcmbal_tm_bac_fields, .classifier_idx = 0, .union_fields = type_descr_bcmbal_tm_bac_union_fields } } };
+bcmcli_enum_val bcmbal_tm_creation_mode_string_table[] = { { .name = "manual", .val = BCMBAL_TM_CREATION_MODE_MANUAL }, { .name = "auto", .val = BCMBAL_TM_CREATION_MODE_AUTO }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_creation_mode = { .name = "bcmbal_tm_creation_mode", .descr = "TM Creation Mode", .size = sizeof(bcmbal_tm_creation_mode), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_creation_mode_string_table } };
+bcmcli_enum_val bcmbal_tm_queue_cfg_id_string_table[] = { { .name = "priority", .val = BCMBAL_TM_QUEUE_CFG_ID_PRIORITY }, { .name = "weight", .val = BCMBAL_TM_QUEUE_CFG_ID_WEIGHT }, { .name = "rate", .val = BCMBAL_TM_QUEUE_CFG_ID_RATE }, { .name = "bac", .val = BCMBAL_TM_QUEUE_CFG_ID_BAC }, { .name = "creation_mode", .val = BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE }, { .name = "ref_count", .val = BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_cfg_id = { .name = "bcmbal_tm_queue_cfg_id", .descr = "Identifiers for all properties contained in the tm_queue_cfg group.", .size = sizeof(bcmbal_tm_queue_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_queue_cfg_id_string_table } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_id_list_u8 = { .name = "bcmbal_tm_queue_id_list_u8", .descr = "Variable-length list of tm_queue_id", .size = sizeof(bcmbal_tm_queue_id_list_u8), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint8_t, .len_size = 1, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_tm_queue_id) } } };
+bcmcli_enum_val bcmbal_tm_queue_ind_id_string_table[] = { { .name = "ret", .val = BCMBAL_TM_QUEUE_IND_ID_RET }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_ind_id = { .name = "bcmbal_tm_queue_ind_id", .descr = "Identifiers for all properties contained in the tm_queue_ind group.", .size = sizeof(bcmbal_tm_queue_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_queue_ind_id_string_table } };
+bcmcli_enum_val bcmbal_tm_queue_key_id_string_table[] = { { .name = "sched_id", .val = BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID }, { .name = "sched_dir", .val = BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR }, { .name = "id", .val = BCMBAL_TM_QUEUE_KEY_ID_ID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_key_id = { .name = "bcmbal_tm_queue_key_id", .descr = "Identifiers for all properties contained in the tm_queue_key group.", .size = sizeof(bcmbal_tm_queue_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_queue_key_id_string_table } };
+bcmcli_enum_val bcmbal_tm_queue_stat_id_string_table[] = { { .name = "packets_ok", .val = BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK }, { .name = "bytes_ok", .val = BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK }, { .name = "packets_discarded", .val = BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED }, { .name = "bytes_discarded", .val = BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_stat_id = { .name = "bcmbal_tm_queue_stat_id", .descr = "Identifiers for all properties contained in the tm_queue_stat group.", .size = sizeof(bcmbal_tm_queue_stat_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_queue_stat_id_string_table } };
+bcmcli_enum_val bcmbal_tm_sched_cfg_id_string_table[] = { { .name = "owner", .val = BCMBAL_TM_SCHED_CFG_ID_OWNER }, { .name = "sched_type", .val = BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE }, { .name = "sched_parent", .val = BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT }, { .name = "sched_child_type", .val = BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE }, { .name = "rate", .val = BCMBAL_TM_SCHED_CFG_ID_RATE }, { .name = "tcont_sla", .val = BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA }, { .name = "creation_mode", .val = BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE }, { .name = "queues", .val = BCMBAL_TM_SCHED_CFG_ID_QUEUES }, { .name = "sub_scheds", .val = BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS }, { .name = "num_priorities", .val = BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_cfg_id = { .name = "bcmbal_tm_sched_cfg_id", .descr = "Identifiers for all properties contained in the tm_sched_cfg group.", .size = sizeof(bcmbal_tm_sched_cfg_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_cfg_id_string_table } };
+bcmcli_enum_val bcmbal_tm_sched_child_type_string_table[] = { { .name = "queue", .val = BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE }, { .name = "sched", .val = BCMBAL_TM_SCHED_CHILD_TYPE_SCHED }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_child_type = { .name = "bcmbal_tm_sched_child_type", .descr = "Scheduling Level for the Children TM ", .size = sizeof(bcmbal_tm_sched_child_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_child_type_string_table } };
+bcmcli_enum_val bcmbal_tm_sched_dir_string_table[] = { { .name = "us", .val = BCMBAL_TM_SCHED_DIR_US }, { .name = "ds", .val = BCMBAL_TM_SCHED_DIR_DS }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_dir = { .name = "bcmbal_tm_sched_dir", .descr = "Traffic Direction", .size = sizeof(bcmbal_tm_sched_dir), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_dir_string_table } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_id_list_u8 = { .name = "bcmbal_tm_sched_id_list_u8", .descr = "Variable-length list of tm_sched_id", .size = sizeof(bcmbal_tm_sched_id_list_u8), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint32_t, .len_size = 1, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(bcmbal_tm_sched_id) } } };
+bcmcli_enum_val bcmbal_tm_sched_ind_id_string_table[] = { { .name = "ret", .val = BCMBAL_TM_SCHED_IND_ID_RET }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_ind_id = { .name = "bcmbal_tm_sched_ind_id", .descr = "Identifiers for all properties contained in the tm_sched_ind group.", .size = sizeof(bcmbal_tm_sched_ind_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_ind_id_string_table } };
+bcmcli_enum_val bcmbal_tm_sched_key_id_string_table[] = { { .name = "dir", .val = BCMBAL_TM_SCHED_KEY_ID_DIR }, { .name = "id", .val = BCMBAL_TM_SCHED_KEY_ID_ID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_key_id = { .name = "bcmbal_tm_sched_key_id", .descr = "Identifiers for all properties contained in the tm_sched_key group.", .size = sizeof(bcmbal_tm_sched_key_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_key_id_string_table } };
+bcmcli_enum_val bcmbal_tm_sched_owner_type_string_table[] = { { .name = "undefined", .val = BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED }, { .name = "interface", .val = BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE }, { .name = "sub_term", .val = BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM }, { .name = "agg_port", .val = BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT }, { .name = "uni", .val = BCMBAL_TM_SCHED_OWNER_TYPE_UNI }, { .name = "virtual", .val = BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_type = { .name = "bcmbal_tm_sched_owner_type", .descr = "TM Scheduler Owner Type", .size = sizeof(bcmbal_tm_sched_owner_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_owner_type_string_table } };
+bcmcli_enum_val bcmbal_tm_sched_owner_agg_port_id_string_table[] = { { .name = "none", .val = BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_NONE }, { .name = "intf_id", .val = BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_INTF_ID }, { .name = "sub_term_id", .val = BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_SUB_TERM_ID }, { .name = "agg_port_id", .val = BCMBAL_TM_SCHED_OWNER_AGG_PORT_ID_AGG_PORT_ID }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_agg_port_id = { .name = "bcmbal_tm_sched_owner_agg_port_id", .descr = "tm_sched_owner agg_port ID", .size = sizeof(bcmbal_tm_sched_owner_agg_port_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_tm_sched_owner_agg_port_id_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_fields[] = { { .name = "type", .descr = "Owner type", .offset = offsetof(bcmbal_tm_sched_owner, type), .type = &type_descr_bcmbal_tm_sched_owner_type } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_interface_fields[] = { { .name = "intf_type", .descr = "Interface Type", .offset = offsetof(bcmbal_tm_sched_owner, u.interface.intf_type) - offsetof(bcmbal_tm_sched_owner, u.interface.intf_type), .type = &type_descr_bcmbal_intf_type }, { .name = "intf_id", .descr = "Interface ID", .offset = offsetof(bcmbal_tm_sched_owner, u.interface.intf_id) - offsetof(bcmbal_tm_sched_owner, u.interface.intf_type), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_interface = { .name = "bcmbal_tm_sched_owner_interface", .descr = "tm_sched_owner interface", .size = sizeof(((bcmbal_tm_sched_owner *)0)->u.interface), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_owner_interface_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_owner_interface_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_sub_term_fields[] = { { .name = "intf_id", .descr = "PON interface id", .offset = offsetof(bcmbal_tm_sched_owner, u.sub_term.intf_id) - offsetof(bcmbal_tm_sched_owner, u.sub_term.intf_id), .type = &type_descr_uint32_t }, { .name = "sub_term_id", .descr = "Subscriber terminal ID", .offset = offsetof(bcmbal_tm_sched_owner, u.sub_term.sub_term_id) - offsetof(bcmbal_tm_sched_owner, u.sub_term.intf_id), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_sub_term = { .name = "bcmbal_tm_sched_owner_sub_term", .descr = "tm_sched_owner subs_term", .size = sizeof(((bcmbal_tm_sched_owner *)0)->u.sub_term), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_owner_sub_term_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_owner_sub_term_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_agg_port_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_tm_sched_owner, u.agg_port.presence_mask) - offsetof(bcmbal_tm_sched_owner, u.agg_port.presence_mask), .type = &type_descr_bcmbal_tm_sched_owner_agg_port_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "intf_id", .descr = "PON interface id", .offset = offsetof(bcmbal_tm_sched_owner, u.agg_port.intf_id) - offsetof(bcmbal_tm_sched_owner, u.agg_port.presence_mask), .type = &type_descr_uint8_t }, { .name = "sub_term_id", .descr = "Subscriber terminal id", .offset = offsetof(bcmbal_tm_sched_owner, u.agg_port.sub_term_id) - offsetof(bcmbal_tm_sched_owner, u.agg_port.presence_mask), .type = &type_descr_uint32_t }, { .name = "agg_port_id", .descr = "Aggregation port id", .offset = offsetof(bcmbal_tm_sched_owner, u.agg_port.agg_port_id) - offsetof(bcmbal_tm_sched_owner, u.agg_port.presence_mask), .type = &type_descr_uint16_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_agg_port = { .name = "bcmbal_tm_sched_owner_agg_port", .descr = "tm_sched_owner agg_port", .size = sizeof(((bcmbal_tm_sched_owner *)0)->u.agg_port), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_owner_agg_port_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_owner_agg_port_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_uni_fields[] = { { .name = "intf_id", .descr = "PON interface id", .offset = offsetof(bcmbal_tm_sched_owner, u.uni.intf_id) - offsetof(bcmbal_tm_sched_owner, u.uni.intf_id), .type = &type_descr_uint8_t }, { .name = "sub_term_id", .descr = "Subscriber terminal id", .offset = offsetof(bcmbal_tm_sched_owner, u.uni.sub_term_id) - offsetof(bcmbal_tm_sched_owner, u.uni.intf_id), .type = &type_descr_uint32_t }, { .name = "idx", .descr = "Index at subscriber terminal", .offset = offsetof(bcmbal_tm_sched_owner, u.uni.idx) - offsetof(bcmbal_tm_sched_owner, u.uni.intf_id), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_uni = { .name = "bcmbal_tm_sched_owner_uni", .descr = "tm_sched_owner uni", .size = sizeof(((bcmbal_tm_sched_owner *)0)->u.uni), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_owner_uni_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_owner_uni_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_virtual_fields[] = { { .name = "idx", .descr = "Owner index", .offset = offsetof(bcmbal_tm_sched_owner, u.virtual.idx) - offsetof(bcmbal_tm_sched_owner, u.virtual.idx), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_virtual = { .name = "bcmbal_tm_sched_owner_virtual", .descr = "tm_sched_owner virtual", .size = sizeof(((bcmbal_tm_sched_owner *)0)->u.virtual), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_owner_virtual_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_owner_virtual_fields } } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner_union_fields[] = { { }, { .name = "u.interface", .descr = "", .offset = offsetof(bcmbal_tm_sched_owner, u.interface), .type = &type_descr_bcmbal_tm_sched_owner_interface }, { .name = "u.sub_term", .descr = "", .offset = offsetof(bcmbal_tm_sched_owner, u.sub_term), .type = &type_descr_bcmbal_tm_sched_owner_sub_term }, { .name = "u.agg_port", .descr = "", .offset = offsetof(bcmbal_tm_sched_owner, u.agg_port), .type = &type_descr_bcmbal_tm_sched_owner_agg_port }, { .name = "u.uni", .descr = "", .offset = offsetof(bcmbal_tm_sched_owner, u.uni), .type = &type_descr_bcmbal_tm_sched_owner_uni }, { .name = "u.virtual", .descr = "", .offset = offsetof(bcmbal_tm_sched_owner, u.virtual), .type = &type_descr_bcmbal_tm_sched_owner_virtual }, { } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_owner = { .name = "bcmbal_tm_sched_owner", .descr = "TM Scheduler Owner", .size = sizeof(bcmbal_tm_sched_owner), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_UNION, .x = { .u = { .num_common_fields = sizeof(type_descr_bcmbal_tm_sched_owner_fields) / sizeof(bcmbal_apicli_field_descr), .common_fields = type_descr_bcmbal_tm_sched_owner_fields, .classifier_idx = 0, .union_fields = type_descr_bcmbal_tm_sched_owner_union_fields } } };
+bcmcli_enum_val bcmbal_tm_sched_parent_id_string_table[] = { { .name = "none", .val = BCMBAL_TM_SCHED_PARENT_ID_NONE }, { .name = "sched_id", .val = BCMBAL_TM_SCHED_PARENT_ID_SCHED_ID }, { .name = "priority", .val = BCMBAL_TM_SCHED_PARENT_ID_PRIORITY }, { .name = "weight", .val = BCMBAL_TM_SCHED_PARENT_ID_WEIGHT }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_parent_id = { .name = "bcmbal_tm_sched_parent_id", .descr = "tm_sched_parent ID", .size = sizeof(bcmbal_tm_sched_parent_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_tm_sched_parent_id_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_parent_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_tm_sched_parent, presence_mask), .type = &type_descr_bcmbal_tm_sched_parent_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "sched_id", .descr = "Parent scheduler id", .offset = offsetof(bcmbal_tm_sched_parent, sched_id), .type = &type_descr_uint32_t }, { .name = "priority", .descr = "Priority", .offset = offsetof(bcmbal_tm_sched_parent, priority), .type = &type_descr_uint8_t }, { .name = "weight", .descr = "Weight", .offset = offsetof(bcmbal_tm_sched_parent, weight), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_parent = { .name = "bcmbal_tm_sched_parent", .descr = "Scheduling Parent Connect Point", .size = sizeof(bcmbal_tm_sched_parent), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_parent_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_parent_fields } } };
+bcmcli_enum_val bcmbal_tm_sched_type_string_table[] = { { .name = "none", .val = BCMBAL_TM_SCHED_TYPE_NONE }, { .name = "wfq", .val = BCMBAL_TM_SCHED_TYPE_WFQ }, { .name = "sp", .val = BCMBAL_TM_SCHED_TYPE_SP }, { .name = "sp_wfq", .val = BCMBAL_TM_SCHED_TYPE_SP_WFQ }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_type = { .name = "bcmbal_tm_sched_type", .descr = "Scheduler Type", .size = sizeof(bcmbal_tm_sched_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_tm_sched_type_string_table } };
+bcmcli_enum_val bcmbal_tm_shaping_id_string_table[] = { { .name = "none", .val = BCMBAL_TM_SHAPING_ID_NONE }, { .name = "sbr", .val = BCMBAL_TM_SHAPING_ID_SBR }, { .name = "pbr", .val = BCMBAL_TM_SHAPING_ID_PBR }, { .name = "burst", .val = BCMBAL_TM_SHAPING_ID_BURST }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_shaping_id = { .name = "bcmbal_tm_shaping_id", .descr = "tm_shaping ID", .size = sizeof(bcmbal_tm_shaping_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_tm_shaping_id_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_shaping_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_tm_shaping, presence_mask), .type = &type_descr_bcmbal_tm_shaping_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "sbr", .descr = "Sustained Bit Rate (kbps)", .offset = offsetof(bcmbal_tm_shaping, sbr), .type = &type_descr_uint32_t }, { .name = "pbr", .descr = "Peak Bit Rate (kbps)", .offset = offsetof(bcmbal_tm_shaping, pbr), .type = &type_descr_uint32_t }, { .name = "burst", .descr = "Max Burst Bytes at Peak Bit Rate", .offset = offsetof(bcmbal_tm_shaping, burst), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_shaping = { .name = "bcmbal_tm_shaping", .descr = "Shaping Parameters", .size = sizeof(bcmbal_tm_shaping), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_shaping_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_shaping_fields } } };
+bcmcli_enum_val bcmbal_tm_tcont_sla_id_string_table[] = { { .name = "none", .val = BCMBAL_TM_TCONT_SLA_ID_NONE }, { .name = "extra_bw_elig", .val = BCMBAL_TM_TCONT_SLA_ID_EXTRA_BW_ELIG }, { .name = "nrt_cbr", .val = BCMBAL_TM_TCONT_SLA_ID_NRT_CBR }, { .name = "rt_cbr", .val = BCMBAL_TM_TCONT_SLA_ID_RT_CBR }, { .name = "rt_profile", .val = BCMBAL_TM_TCONT_SLA_ID_RT_PROFILE }, { .name = "nrt_profile", .val = BCMBAL_TM_TCONT_SLA_ID_NRT_PROFILE }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_tcont_sla_id = { .name = "bcmbal_tm_tcont_sla_id", .descr = "tm_tcont_sla ID", .size = sizeof(bcmbal_tm_tcont_sla_id), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, .x = { .e = bcmbal_tm_tcont_sla_id_string_table } };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_tcont_sla_fields[] = { { .name = "presence_mask", .descr = "Presence Mask", .offset = offsetof(bcmbal_tm_tcont_sla, presence_mask), .type = &type_descr_bcmbal_tm_tcont_sla_id, .flags = BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK }, { .name = "extra_bw_elig", .descr = "Extra BW eligibility type", .offset = offsetof(bcmbal_tm_tcont_sla, extra_bw_elig), .type = &type_descr_bcmbal_extra_bw_eligibility_type }, { .name = "nrt_cbr", .descr = "NRT CBR", .offset = offsetof(bcmbal_tm_tcont_sla, nrt_cbr), .type = &type_descr_uint8_t }, { .name = "rt_cbr", .descr = "RT_CBR", .offset = offsetof(bcmbal_tm_tcont_sla, rt_cbr), .type = &type_descr_uint8_t }, { .name = "rt_profile", .descr = "RT Profile", .offset = offsetof(bcmbal_tm_tcont_sla, rt_profile), .type = &type_descr_uint8_t }, { .name = "nrt_profile", .descr = "NRT Profile", .offset = offsetof(bcmbal_tm_tcont_sla, nrt_profile), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_tcont_sla = { .name = "bcmbal_tm_tcont_sla", .descr = "ITU-PON Extended SLA Parameters", .size = sizeof(bcmbal_tm_tcont_sla), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_tcont_sla_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_tcont_sla_fields } } };
+bcmcli_enum_val bcmbal_trx_type_string_table[] = { { .name = "gpon_sps_43_48", .val = BCMBAL_TRX_TYPE_GPON_SPS_43_48 }, { .name = "gpon_sps_sog_4321", .val = BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321 }, { .name = "gpon_lte_3680_m", .val = BCMBAL_TRX_TYPE_GPON_LTE_3680_M }, { .name = "gpon_source_photonics", .val = BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS }, { .name = "gpon_lte_3680_p", .val = BCMBAL_TRX_TYPE_GPON_LTE_3680_P }, { .name = "xgpon_lth_7222_pc", .val = BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC }, { .name = "xgpon_lth_7226_pc", .val = BCMBAL_TRX_TYPE_XGPON_LTH_7226_PC }, { .name = "xgpon_lth_5302_pc", .val = BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC }, BCMCLI_ENUM_LAST };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_trx_type = { .name = "bcmbal_trx_type", .descr = "Transceiver types", .size = sizeof(bcmbal_trx_type), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ENUM, .x = { .e = bcmbal_trx_type_string_table } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_u8_list_u32 = { .name = "bcmbal_u8_list_u32", .descr = "Variable-length list of U8", .size = sizeof(bcmbal_u8_list_u32), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, .x = { .arr_dyn = { .elem_type = &type_descr_uint8_t, .len_size = 4, .max_size = DEFAULT_DYN_ARR_MAX_SIZE / sizeof(uint8_t) } } };
+
+/* ==== Object: access_terminal ==== */
+
+/* Group: access_terminal - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_key_access_term_id = { .name = "access_term_id", .descr = "Reserved (set to 0)", .access = 0, .property = BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID, .offset = offsetof(bcmbal_access_terminal_key, access_term_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR access_terminal_key_prop_array[] = { &prop_descr_access_terminal_key_access_term_id };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_access_terminal_key_fields[] = { { .name = "access_term_id", .descr = "Reserved (set to 0)", .offset = offsetof(bcmbal_access_terminal_key, access_term_id), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_access_terminal_key = { .name = "bcmbal_access_terminal_key", .descr = "key", .size = sizeof(bcmbal_access_terminal_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_access_terminal_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_access_terminal_key_fields } } };
+
+/* Group: access_terminal - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_cfg_admin_state = { .name = "admin_state", .descr = "Administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE, .offset = offsetof(bcmbal_access_terminal_cfg_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_cfg_oper_status = { .name = "oper_status", .descr = "Operational status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS, .offset = offsetof(bcmbal_access_terminal_cfg_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_cfg_iwf_mode = { .name = "iwf_mode", .descr = "The interworking mode", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE, .offset = offsetof(bcmbal_access_terminal_cfg_data, iwf_mode), .type = &type_descr_bcmbal_iwf_mode };
+static bcmbal_apicli_prop_descr * BCM_DESCR access_terminal_cfg_prop_array[] = { &prop_descr_access_terminal_cfg_admin_state, &prop_descr_access_terminal_cfg_oper_status, &prop_descr_access_terminal_cfg_iwf_mode };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_access_terminal_cfg_data_fields[] = { { .name = "admin_state", .descr = "Administrative state", .offset = offsetof(bcmbal_access_terminal_cfg_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Operational status", .offset = offsetof(bcmbal_access_terminal_cfg_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "iwf_mode", .descr = "The interworking mode", .offset = offsetof(bcmbal_access_terminal_cfg_data, iwf_mode), .type = &type_descr_bcmbal_iwf_mode } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_access_terminal_cfg_data = { .name = "bcmbal_access_terminal_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_access_terminal_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_access_terminal_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_access_terminal_cfg_data_fields } } };
+
+/* Group: access_terminal - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_ind_admin_state = { .name = "admin_state", .descr = "Current administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE, .offset = offsetof(bcmbal_access_terminal_ind_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_ind_oper_status = { .name = "oper_status", .descr = "Current operational status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS, .offset = offsetof(bcmbal_access_terminal_ind_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_access_terminal_ind_iwf_mode = { .name = "iwf_mode", .descr = "The interworking mode", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE, .offset = offsetof(bcmbal_access_terminal_ind_data, iwf_mode), .type = &type_descr_bcmbal_iwf_mode };
+static bcmbal_apicli_prop_descr * BCM_DESCR access_terminal_ind_prop_array[] = { &prop_descr_access_terminal_ind_admin_state, &prop_descr_access_terminal_ind_oper_status, &prop_descr_access_terminal_ind_iwf_mode };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_access_terminal_ind_data_fields[] = { { .name = "admin_state", .descr = "Current administrative state", .offset = offsetof(bcmbal_access_terminal_ind_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Current operational status", .offset = offsetof(bcmbal_access_terminal_ind_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "iwf_mode", .descr = "The interworking mode", .offset = offsetof(bcmbal_access_terminal_ind_data, iwf_mode), .type = &type_descr_bcmbal_iwf_mode } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_access_terminal_ind_data = { .name = "bcmbal_access_terminal_ind_data", .descr = "Access Terminal Indication", .size = sizeof(bcmbal_access_terminal_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_access_terminal_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_access_terminal_ind_data_fields } } };
+
+/* ==== Object: flow ==== */
+
+/* Group: flow - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_admin_state = { .name = "admin_state", .descr = "Administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_ADMIN_STATE, .offset = offsetof(bcmbal_flow_cfg_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_oper_status = { .name = "oper_status", .descr = "Operational status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_FLOW_CFG_ID_OPER_STATUS, .offset = offsetof(bcmbal_flow_cfg_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_access_int_id = { .name = "access_int_id", .descr = "The ID of the subscriber side interface; i.e. PON", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID, .offset = offsetof(bcmbal_flow_cfg_data, access_int_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_network_int_id = { .name = "network_int_id", .descr = "The ID of the network side interface; i.e. NNI", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID, .offset = offsetof(bcmbal_flow_cfg_data, network_int_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_sub_term_id = { .name = "sub_term_id", .descr = "The ID of the subsccriber terminal device", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_SUB_TERM_ID, .offset = offsetof(bcmbal_flow_cfg_data, sub_term_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_sub_term_uni_idx = { .name = "sub_term_uni_idx", .descr = "The index of the subsccriber terminal uni port the flow is related to", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX, .offset = offsetof(bcmbal_flow_cfg_data, sub_term_uni_idx), .type = &type_descr_uint8_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_svc_port_id = { .name = "svc_port_id", .descr = "The ID of the service port (for GPON/XGPON - GEM ID)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_SVC_PORT_ID, .offset = offsetof(bcmbal_flow_cfg_data, svc_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_agg_port_id = { .name = "agg_port_id", .descr = "The ID of the aggregate port (for GPON/XGPON - ALLOC ID)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_AGG_PORT_ID, .offset = offsetof(bcmbal_flow_cfg_data, agg_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_resolve_mac = { .name = "resolve_mac", .descr = "A flag indicating if the MAC address table should be used in DS GEM resolution", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_RESOLVE_MAC, .offset = offsetof(bcmbal_flow_cfg_data, resolve_mac), .type = &type_descr_bcmos_bool };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_classifier = { .name = "classifier", .descr = "The classifier for this flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_CLASSIFIER, .offset = offsetof(bcmbal_flow_cfg_data, classifier), .type = &type_descr_bcmbal_classifier };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_action = { .name = "action", .descr = "The action associated with the flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_ACTION, .offset = offsetof(bcmbal_flow_cfg_data, action), .type = &type_descr_bcmbal_action };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_sla = { .name = "sla", .descr = "SLA parameters for this flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_SLA, .offset = offsetof(bcmbal_flow_cfg_data, sla), .type = &type_descr_bcmbal_sla };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_cookie = { .name = "cookie", .descr = "Application cookie", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_COOKIE, .offset = offsetof(bcmbal_flow_cfg_data, cookie), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_priority = { .name = "priority", .descr = "Priority", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_PRIORITY, .offset = offsetof(bcmbal_flow_cfg_data, priority), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_group_id = { .name = "group_id", .descr = "RW - The multicast group associated with this flow, valid for type MULTICAST only", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_GROUP_ID, .offset = offsetof(bcmbal_flow_cfg_data, group_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_cfg_queue = { .name = "queue", .descr = "Egress queue", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_CFG_ID_QUEUE, .offset = offsetof(bcmbal_flow_cfg_data, queue), .type = &type_descr_bcmbal_tm_queue_ref };
+static bcmbal_apicli_prop_descr * BCM_DESCR flow_cfg_prop_array[] = { &prop_descr_flow_cfg_admin_state, &prop_descr_flow_cfg_oper_status, &prop_descr_flow_cfg_access_int_id, &prop_descr_flow_cfg_network_int_id, &prop_descr_flow_cfg_sub_term_id, &prop_descr_flow_cfg_sub_term_uni_idx, &prop_descr_flow_cfg_svc_port_id, &prop_descr_flow_cfg_agg_port_id, &prop_descr_flow_cfg_resolve_mac, &prop_descr_flow_cfg_classifier, &prop_descr_flow_cfg_action, &prop_descr_flow_cfg_sla, &prop_descr_flow_cfg_cookie, &prop_descr_flow_cfg_priority, &prop_descr_flow_cfg_group_id, &prop_descr_flow_cfg_queue };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_flow_cfg_data_fields[] = { { .name = "admin_state", .descr = "Administrative state", .offset = offsetof(bcmbal_flow_cfg_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Operational status", .offset = offsetof(bcmbal_flow_cfg_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "access_int_id", .descr = "The ID of the subscriber side interface; i.e. PON", .offset = offsetof(bcmbal_flow_cfg_data, access_int_id), .type = &type_descr_uint32_t }, { .name = "network_int_id", .descr = "The ID of the network side interface; i.e. NNI", .offset = offsetof(bcmbal_flow_cfg_data, network_int_id), .type = &type_descr_uint32_t }, { .name = "sub_term_id", .descr = "The ID of the subsccriber terminal device", .offset = offsetof(bcmbal_flow_cfg_data, sub_term_id), .type = &type_descr_uint32_t }, { .name = "sub_term_uni_idx", .descr = "The index of the subsccriber terminal uni port the flow is related to", .offset = offsetof(bcmbal_flow_cfg_data, sub_term_uni_idx), .type = &type_descr_uint8_t }, { .name = "svc_port_id", .descr = "The ID of the service port (for GPON/XGPON - GEM ID)", .offset = offsetof(bcmbal_flow_cfg_data, svc_port_id), .type = &type_descr_uint16_t }, { .name = "agg_port_id", .descr = "The ID of the aggregate port (for GPON/XGPON - ALLOC ID)", .offset = offsetof(bcmbal_flow_cfg_data, agg_port_id), .type = &type_descr_uint16_t }, { .name = "resolve_mac", .descr = "A flag indicating if the MAC address table should be used in DS GEM resolution", .offset = offsetof(bcmbal_flow_cfg_data, resolve_mac), .type = &type_descr_bcmos_bool }, { .name = "classifier", .descr = "The classifier for this flow", .offset = offsetof(bcmbal_flow_cfg_data, classifier), .type = &type_descr_bcmbal_classifier }, { .name = "action", .descr = "The action associated with the flow", .offset = offsetof(bcmbal_flow_cfg_data, action), .type = &type_descr_bcmbal_action }, { .name = "sla", .descr = "SLA parameters for this flow", .offset = offsetof(bcmbal_flow_cfg_data, sla), .type = &type_descr_bcmbal_sla }, { .name = "cookie", .descr = "Application cookie", .offset = offsetof(bcmbal_flow_cfg_data, cookie), .type = &type_descr_uint64_t }, { .name = "priority", .descr = "Priority", .offset = offsetof(bcmbal_flow_cfg_data, priority), .type = &type_descr_uint16_t }, { .name = "group_id", .descr = "RW - The multicast group associated with this flow, valid for type MULTICAST only", .offset = offsetof(bcmbal_flow_cfg_data, group_id), .type = &type_descr_uint32_t }, { .name = "queue", .descr = "Egress queue", .offset = offsetof(bcmbal_flow_cfg_data, queue), .type = &type_descr_bcmbal_tm_queue_ref } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_cfg_data = { .name = "bcmbal_flow_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_flow_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_flow_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_flow_cfg_data_fields } } };
+
+/* Group: flow - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_key_flow_id = { .name = "flow_id", .descr = "The ID of the flow object instance being referenced", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_KEY_ID_FLOW_ID, .offset = offsetof(bcmbal_flow_key, flow_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_key_flow_type = { .name = "flow_type", .descr = "The type of the flow, Upstream, Downstream, Broadcast or Multicast", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_KEY_ID_FLOW_TYPE, .offset = offsetof(bcmbal_flow_key, flow_type), .type = &type_descr_bcmbal_flow_type };
+static bcmbal_apicli_prop_descr * BCM_DESCR flow_key_prop_array[] = { &prop_descr_flow_key_flow_id, &prop_descr_flow_key_flow_type };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_flow_key_fields[] = { { .name = "flow_id", .descr = "The ID of the flow object instance being referenced", .offset = offsetof(bcmbal_flow_key, flow_id), .type = &type_descr_uint32_t }, { .name = "flow_type", .descr = "The type of the flow, Upstream, Downstream, Broadcast or Multicast", .offset = offsetof(bcmbal_flow_key, flow_type), .type = &type_descr_bcmbal_flow_type } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_key = { .name = "bcmbal_flow_key", .descr = "key", .size = sizeof(bcmbal_flow_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_flow_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_flow_key_fields } } };
+
+/* Group: flow - stat */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_stat_rx_packets = { .name = "rx_packets", .descr = "Received packets", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_STAT_ID_RX_PACKETS, .offset = offsetof(bcmbal_flow_stat_data, rx_packets), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_stat_rx_bytes = { .name = "rx_bytes", .descr = "Received bytes", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_STAT_ID_RX_BYTES, .offset = offsetof(bcmbal_flow_stat_data, rx_bytes), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_stat_tx_packets = { .name = "tx_packets", .descr = "Transmitted packets", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_STAT_ID_TX_PACKETS, .offset = offsetof(bcmbal_flow_stat_data, tx_packets), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_stat_tx_bytes = { .name = "tx_bytes", .descr = "Transmitted bytes", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_STAT_ID_TX_BYTES, .offset = offsetof(bcmbal_flow_stat_data, tx_bytes), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR flow_stat_prop_array[] = { &prop_descr_flow_stat_rx_packets, &prop_descr_flow_stat_rx_bytes, &prop_descr_flow_stat_tx_packets, &prop_descr_flow_stat_tx_bytes };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_flow_stat_data_fields[] = { { .name = "rx_packets", .descr = "Received packets", .offset = offsetof(bcmbal_flow_stat_data, rx_packets), .type = &type_descr_uint64_t }, { .name = "rx_bytes", .descr = "Received bytes", .offset = offsetof(bcmbal_flow_stat_data, rx_bytes), .type = &type_descr_uint64_t }, { .name = "tx_packets", .descr = "Transmitted packets", .offset = offsetof(bcmbal_flow_stat_data, tx_packets), .type = &type_descr_uint64_t }, { .name = "tx_bytes", .descr = "Transmitted bytes", .offset = offsetof(bcmbal_flow_stat_data, tx_bytes), .type = &type_descr_uint64_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_stat_data = { .name = "bcmbal_flow_stat_data", .descr = "stat", .size = sizeof(bcmbal_flow_stat_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_flow_stat_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_flow_stat_data_fields } } };
+
+/* Group: flow - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_admin_state = { .name = "admin_state", .descr = "Administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_ADMIN_STATE, .offset = offsetof(bcmbal_flow_ind_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_oper_status = { .name = "oper_status", .descr = "Operational Status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_OPER_STATUS, .offset = offsetof(bcmbal_flow_ind_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_access_int_id = { .name = "access_int_id", .descr = "The ID of the subscriber side interface; i.e. PON", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_ACCESS_INT_ID, .offset = offsetof(bcmbal_flow_ind_data, access_int_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_network_int_id = { .name = "network_int_id", .descr = "The ID of the network side interface; i.e. NNI", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_NETWORK_INT_ID, .offset = offsetof(bcmbal_flow_ind_data, network_int_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_sub_term_id = { .name = "sub_term_id", .descr = "The ID of the subsccriber terminal device", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_SUB_TERM_ID, .offset = offsetof(bcmbal_flow_ind_data, sub_term_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_svc_port_id = { .name = "svc_port_id", .descr = "The ID of the service port (for GPON/XGPON - GEM ID)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_SVC_PORT_ID, .offset = offsetof(bcmbal_flow_ind_data, svc_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_agg_port_id = { .name = "agg_port_id", .descr = "The ID of the aggregate port (for GPON/XGPON - ALLOC ID)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_AGG_PORT_ID, .offset = offsetof(bcmbal_flow_ind_data, agg_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_resolve_mac = { .name = "resolve_mac", .descr = "A flag indicating if the MAC address table should be used in DS GEM resolution", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_RESOLVE_MAC, .offset = offsetof(bcmbal_flow_ind_data, resolve_mac), .type = &type_descr_bcmos_bool };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_base_tc_id = { .name = "base_tc_id", .descr = "The base index of the TC object(s) to be used for this flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_BASE_TC_ID, .offset = offsetof(bcmbal_flow_ind_data, base_tc_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_classifier = { .name = "classifier", .descr = "The classifier for this flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_CLASSIFIER, .offset = offsetof(bcmbal_flow_ind_data, classifier), .type = &type_descr_bcmbal_classifier };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_action = { .name = "action", .descr = "The action associated with the flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_ACTION, .offset = offsetof(bcmbal_flow_ind_data, action), .type = &type_descr_bcmbal_action };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_sla = { .name = "sla", .descr = "SLA parameters for this flow", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_SLA, .offset = offsetof(bcmbal_flow_ind_data, sla), .type = &type_descr_bcmbal_sla };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_cookie = { .name = "cookie", .descr = "Application cookie", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_COOKIE, .offset = offsetof(bcmbal_flow_ind_data, cookie), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_flow_ind_priority = { .name = "priority", .descr = "Priority", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_FLOW_IND_ID_PRIORITY, .offset = offsetof(bcmbal_flow_ind_data, priority), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR flow_ind_prop_array[] = { &prop_descr_flow_ind_admin_state, &prop_descr_flow_ind_oper_status, &prop_descr_flow_ind_access_int_id, &prop_descr_flow_ind_network_int_id, &prop_descr_flow_ind_sub_term_id, &prop_descr_flow_ind_svc_port_id, &prop_descr_flow_ind_agg_port_id, &prop_descr_flow_ind_resolve_mac, &prop_descr_flow_ind_base_tc_id, &prop_descr_flow_ind_classifier, &prop_descr_flow_ind_action, &prop_descr_flow_ind_sla, &prop_descr_flow_ind_cookie, &prop_descr_flow_ind_priority };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_flow_ind_data_fields[] = { { .name = "admin_state", .descr = "Administrative state", .offset = offsetof(bcmbal_flow_ind_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Operational Status", .offset = offsetof(bcmbal_flow_ind_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "access_int_id", .descr = "The ID of the subscriber side interface; i.e. PON", .offset = offsetof(bcmbal_flow_ind_data, access_int_id), .type = &type_descr_uint16_t }, { .name = "network_int_id", .descr = "The ID of the network side interface; i.e. NNI", .offset = offsetof(bcmbal_flow_ind_data, network_int_id), .type = &type_descr_uint16_t }, { .name = "sub_term_id", .descr = "The ID of the subsccriber terminal device", .offset = offsetof(bcmbal_flow_ind_data, sub_term_id), .type = &type_descr_uint32_t }, { .name = "svc_port_id", .descr = "The ID of the service port (for GPON/XGPON - GEM ID)", .offset = offsetof(bcmbal_flow_ind_data, svc_port_id), .type = &type_descr_uint16_t }, { .name = "agg_port_id", .descr = "The ID of the aggregate port (for GPON/XGPON - ALLOC ID)", .offset = offsetof(bcmbal_flow_ind_data, agg_port_id), .type = &type_descr_uint16_t }, { .name = "resolve_mac", .descr = "A flag indicating if the MAC address table should be used in DS GEM resolution", .offset = offsetof(bcmbal_flow_ind_data, resolve_mac), .type = &type_descr_bcmos_bool }, { .name = "base_tc_id", .descr = "The base index of the TC object(s) to be used for this flow", .offset = offsetof(bcmbal_flow_ind_data, base_tc_id), .type = &type_descr_uint16_t }, { .name = "classifier", .descr = "The classifier for this flow", .offset = offsetof(bcmbal_flow_ind_data, classifier), .type = &type_descr_bcmbal_classifier }, { .name = "action", .descr = "The action associated with the flow", .offset = offsetof(bcmbal_flow_ind_data, action), .type = &type_descr_bcmbal_action }, { .name = "sla", .descr = "SLA parameters for this flow", .offset = offsetof(bcmbal_flow_ind_data, sla), .type = &type_descr_bcmbal_sla }, { .name = "cookie", .descr = "Application cookie", .offset = offsetof(bcmbal_flow_ind_data, cookie), .type = &type_descr_uint32_t }, { .name = "priority", .descr = "Priority", .offset = offsetof(bcmbal_flow_ind_data, priority), .type = &type_descr_uint16_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_flow_ind_data = { .name = "bcmbal_flow_ind_data", .descr = "Flow Indication", .size = sizeof(bcmbal_flow_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_flow_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_flow_ind_data_fields } } };
+
+/* ==== Object: group ==== */
+
+/* Group: group - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_group_cfg_members_cmd = { .name = "members_cmd", .descr = "Membership operation commands", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_GROUP_CFG_ID_MEMBERS_CMD, .offset = offsetof(bcmbal_group_cfg_data, members_cmd), .type = &type_descr_bcmbal_group_member_cmd };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_group_cfg_members = { .name = "members", .descr = "The list of members associated with this group", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_GROUP_CFG_ID_MEMBERS, .offset = offsetof(bcmbal_group_cfg_data, members), .type = &type_descr_bcmbal_group_member_info_list_u16 };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_group_cfg_cookie = { .name = "cookie", .descr = "Application cookie", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_GROUP_CFG_ID_COOKIE, .offset = offsetof(bcmbal_group_cfg_data, cookie), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_group_cfg_flows = { .name = "flows", .descr = "List of flows associated with this group", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_GROUP_CFG_ID_FLOWS, .offset = offsetof(bcmbal_group_cfg_data, flows), .type = &type_descr_bcmbal_flow_id_list_u32 };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_group_cfg_owner = { .name = "owner", .descr = "Owner of the group", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_GROUP_CFG_ID_OWNER, .offset = offsetof(bcmbal_group_cfg_data, owner), .type = &type_descr_bcmbal_group_owner };
+static bcmbal_apicli_prop_descr * BCM_DESCR group_cfg_prop_array[] = { &prop_descr_group_cfg_members_cmd, &prop_descr_group_cfg_members, &prop_descr_group_cfg_cookie, &prop_descr_group_cfg_flows, &prop_descr_group_cfg_owner };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_group_cfg_data_fields[] = { { .name = "members_cmd", .descr = "Membership operation commands", .offset = offsetof(bcmbal_group_cfg_data, members_cmd), .type = &type_descr_bcmbal_group_member_cmd }, { .name = "members", .descr = "The list of members associated with this group", .offset = offsetof(bcmbal_group_cfg_data, members), .type = &type_descr_bcmbal_group_member_info_list_u16 }, { .name = "cookie", .descr = "Application cookie", .offset = offsetof(bcmbal_group_cfg_data, cookie), .type = &type_descr_uint64_t }, { .name = "flows", .descr = "List of flows associated with this group", .offset = offsetof(bcmbal_group_cfg_data, flows), .type = &type_descr_bcmbal_flow_id_list_u32 }, { .name = "owner", .descr = "Owner of the group", .offset = offsetof(bcmbal_group_cfg_data, owner), .type = &type_descr_bcmbal_group_owner } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_cfg_data = { .name = "bcmbal_group_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_group_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_group_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_group_cfg_data_fields } } };
+
+/* Group: group - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_group_key_group_id = { .name = "group_id", .descr = "The ID of the group object instance being referenced", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_GROUP_KEY_ID_GROUP_ID, .offset = offsetof(bcmbal_group_key, group_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR group_key_prop_array[] = { &prop_descr_group_key_group_id };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_group_key_fields[] = { { .name = "group_id", .descr = "The ID of the group object instance being referenced", .offset = offsetof(bcmbal_group_key, group_id), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_group_key = { .name = "bcmbal_group_key", .descr = "key", .size = sizeof(bcmbal_group_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_group_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_group_key_fields } } };
+
+/* ==== Object: interface ==== */
+
+/* Group: interface - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_key_intf_id = { .name = "intf_id", .descr = "intf_id", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_KEY_ID_INTF_ID, .offset = offsetof(bcmbal_interface_key, intf_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_key_intf_type = { .name = "intf_type", .descr = "intf_type", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_KEY_ID_INTF_TYPE, .offset = offsetof(bcmbal_interface_key, intf_type), .type = &type_descr_bcmbal_intf_type };
+static bcmbal_apicli_prop_descr * BCM_DESCR interface_key_prop_array[] = { &prop_descr_interface_key_intf_id, &prop_descr_interface_key_intf_type };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_interface_key_fields[] = { { .name = "intf_id", .descr = "intf_id", .offset = offsetof(bcmbal_interface_key, intf_id), .type = &type_descr_uint32_t }, { .name = "intf_type", .descr = "intf_type", .offset = offsetof(bcmbal_interface_key, intf_type), .type = &type_descr_bcmbal_intf_type } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_key = { .name = "bcmbal_interface_key", .descr = "key", .size = sizeof(bcmbal_interface_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_interface_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_interface_key_fields } } };
+
+/* Group: interface - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_admin_state = { .name = "admin_state", .descr = "Administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE, .offset = offsetof(bcmbal_interface_cfg_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_oper_status = { .name = "oper_status", .descr = "Operational status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_INTERFACE_CFG_ID_OPER_STATUS, .offset = offsetof(bcmbal_interface_cfg_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_min_data_agg_port_id = { .name = "min_data_agg_port_id", .descr = "The minimum agg_port_id that is allowed in the system", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID, .offset = offsetof(bcmbal_interface_cfg_data, min_data_agg_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_min_data_svc_port_id = { .name = "min_data_svc_port_id", .descr = "The minimum svc_port_id that is allowed in the system", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID, .offset = offsetof(bcmbal_interface_cfg_data, min_data_svc_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_transceiver_type = { .name = "transceiver_type", .descr = "The transceiver type used on an interface", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE, .offset = offsetof(bcmbal_interface_cfg_data, transceiver_type), .type = &type_descr_bcmbal_trx_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_ds_miss_mode = { .name = "ds_miss_mode", .descr = "Defines the action to take for unknown downstream packets", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE, .offset = offsetof(bcmbal_interface_cfg_data, ds_miss_mode), .type = &type_descr_bcmbal_ds_miss_mode };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_mtu = { .name = "mtu", .descr = "The MTU for an interface", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_MTU, .offset = offsetof(bcmbal_interface_cfg_data, mtu), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_flow_control = { .name = "flow_control", .descr = "Flow control enable or disable", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL, .offset = offsetof(bcmbal_interface_cfg_data, flow_control), .type = &type_descr_bcmbal_control };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_ds_tm = { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_DS_TM, .offset = offsetof(bcmbal_interface_cfg_data, ds_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_us_tm = { .name = "us_tm", .descr = "Upstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_CFG_ID_US_TM, .offset = offsetof(bcmbal_interface_cfg_data, us_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_cfg_sub_term_id_list = { .name = "sub_term_id_list", .descr = "A list of subscriber terminal ids configured on this interface", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST, .offset = offsetof(bcmbal_interface_cfg_data, sub_term_id_list), .type = &type_descr_bcmbal_sub_id_list_u16 };
+static bcmbal_apicli_prop_descr * BCM_DESCR interface_cfg_prop_array[] = { &prop_descr_interface_cfg_admin_state, &prop_descr_interface_cfg_oper_status, &prop_descr_interface_cfg_min_data_agg_port_id, &prop_descr_interface_cfg_min_data_svc_port_id, &prop_descr_interface_cfg_transceiver_type, &prop_descr_interface_cfg_ds_miss_mode, &prop_descr_interface_cfg_mtu, &prop_descr_interface_cfg_flow_control, &prop_descr_interface_cfg_ds_tm, &prop_descr_interface_cfg_us_tm, &prop_descr_interface_cfg_sub_term_id_list };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_interface_cfg_data_fields[] = { { .name = "admin_state", .descr = "Administrative state", .offset = offsetof(bcmbal_interface_cfg_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Operational status", .offset = offsetof(bcmbal_interface_cfg_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "min_data_agg_port_id", .descr = "The minimum agg_port_id that is allowed in the system", .offset = offsetof(bcmbal_interface_cfg_data, min_data_agg_port_id), .type = &type_descr_uint16_t }, { .name = "min_data_svc_port_id", .descr = "The minimum svc_port_id that is allowed in the system", .offset = offsetof(bcmbal_interface_cfg_data, min_data_svc_port_id), .type = &type_descr_uint16_t }, { .name = "transceiver_type", .descr = "The transceiver type used on an interface", .offset = offsetof(bcmbal_interface_cfg_data, transceiver_type), .type = &type_descr_bcmbal_trx_type }, { .name = "ds_miss_mode", .descr = "Defines the action to take for unknown downstream packets", .offset = offsetof(bcmbal_interface_cfg_data, ds_miss_mode), .type = &type_descr_bcmbal_ds_miss_mode }, { .name = "mtu", .descr = "The MTU for an interface", .offset = offsetof(bcmbal_interface_cfg_data, mtu), .type = &type_descr_uint16_t }, { .name = "flow_control", .descr = "Flow control enable or disable", .offset = offsetof(bcmbal_interface_cfg_data, flow_control), .type = &type_descr_bcmbal_control }, { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .offset = offsetof(bcmbal_interface_cfg_data, ds_tm), .type = &type_descr_uint32_t }, { .name = "us_tm", .descr = "Upstream scheduler and shaper", .offset = offsetof(bcmbal_interface_cfg_data, us_tm), .type = &type_descr_uint32_t }, { .name = "sub_term_id_list", .descr = "A list of subscriber terminal ids configured on this interface", .offset = offsetof(bcmbal_interface_cfg_data, sub_term_id_list), .type = &type_descr_bcmbal_sub_id_list_u16 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_cfg_data = { .name = "bcmbal_interface_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_interface_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_interface_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_interface_cfg_data_fields } } };
+
+/* Group: interface - stat */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_stat_rx_packets = { .name = "rx_packets", .descr = "Recieved packets", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_STAT_ID_RX_PACKETS, .offset = offsetof(bcmbal_interface_stat_data, rx_packets), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_stat_rx_bytes = { .name = "rx_bytes", .descr = "Received bytes", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_STAT_ID_RX_BYTES, .offset = offsetof(bcmbal_interface_stat_data, rx_bytes), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_stat_tx_packets = { .name = "tx_packets", .descr = "Transmitted packets", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_STAT_ID_TX_PACKETS, .offset = offsetof(bcmbal_interface_stat_data, tx_packets), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_stat_tx_bytes = { .name = "tx_bytes", .descr = "Transmitted bytes", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_STAT_ID_TX_BYTES, .offset = offsetof(bcmbal_interface_stat_data, tx_bytes), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR interface_stat_prop_array[] = { &prop_descr_interface_stat_rx_packets, &prop_descr_interface_stat_rx_bytes, &prop_descr_interface_stat_tx_packets, &prop_descr_interface_stat_tx_bytes };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_interface_stat_data_fields[] = { { .name = "rx_packets", .descr = "Recieved packets", .offset = offsetof(bcmbal_interface_stat_data, rx_packets), .type = &type_descr_uint64_t }, { .name = "rx_bytes", .descr = "Received bytes", .offset = offsetof(bcmbal_interface_stat_data, rx_bytes), .type = &type_descr_uint64_t }, { .name = "tx_packets", .descr = "Transmitted packets", .offset = offsetof(bcmbal_interface_stat_data, tx_packets), .type = &type_descr_uint64_t }, { .name = "tx_bytes", .descr = "Transmitted bytes", .offset = offsetof(bcmbal_interface_stat_data, tx_bytes), .type = &type_descr_uint64_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_stat_data = { .name = "bcmbal_interface_stat_data", .descr = "stat", .size = sizeof(bcmbal_interface_stat_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_interface_stat_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_interface_stat_data_fields } } };
+
+/* Group: interface - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_admin_state = { .name = "admin_state", .descr = "Current administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_ADMIN_STATE, .offset = offsetof(bcmbal_interface_ind_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_oper_status = { .name = "oper_status", .descr = "Current operational state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_OPER_STATUS, .offset = offsetof(bcmbal_interface_ind_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_min_data_agg_port_id = { .name = "min_data_agg_port_id", .descr = "The minimum agg_port_id that is allowed in the system", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID, .offset = offsetof(bcmbal_interface_ind_data, min_data_agg_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_min_data_svc_port_id = { .name = "min_data_svc_port_id", .descr = "The minimum svc_port_id that is allowed in the system", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID, .offset = offsetof(bcmbal_interface_ind_data, min_data_svc_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_transceiver_type = { .name = "transceiver_type", .descr = "The transceiver type used on an interface", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE, .offset = offsetof(bcmbal_interface_ind_data, transceiver_type), .type = &type_descr_bcmbal_trx_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_ds_miss_mode = { .name = "ds_miss_mode", .descr = "Defines the action to take for DS unknown packets", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE, .offset = offsetof(bcmbal_interface_ind_data, ds_miss_mode), .type = &type_descr_bcmbal_ds_miss_mode };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_mtu = { .name = "mtu", .descr = "The MTU for an interface", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_MTU, .offset = offsetof(bcmbal_interface_ind_data, mtu), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_flow_control = { .name = "flow_control", .descr = "Flow control enable or disable", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL, .offset = offsetof(bcmbal_interface_ind_data, flow_control), .type = &type_descr_bcmbal_control };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_ds_tm = { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_DS_TM, .offset = offsetof(bcmbal_interface_ind_data, ds_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_interface_ind_us_tm = { .name = "us_tm", .descr = "Upstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_INTERFACE_IND_ID_US_TM, .offset = offsetof(bcmbal_interface_ind_data, us_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR interface_ind_prop_array[] = { &prop_descr_interface_ind_admin_state, &prop_descr_interface_ind_oper_status, &prop_descr_interface_ind_min_data_agg_port_id, &prop_descr_interface_ind_min_data_svc_port_id, &prop_descr_interface_ind_transceiver_type, &prop_descr_interface_ind_ds_miss_mode, &prop_descr_interface_ind_mtu, &prop_descr_interface_ind_flow_control, &prop_descr_interface_ind_ds_tm, &prop_descr_interface_ind_us_tm };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_interface_ind_data_fields[] = { { .name = "admin_state", .descr = "Current administrative state", .offset = offsetof(bcmbal_interface_ind_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Current operational state", .offset = offsetof(bcmbal_interface_ind_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "min_data_agg_port_id", .descr = "The minimum agg_port_id that is allowed in the system", .offset = offsetof(bcmbal_interface_ind_data, min_data_agg_port_id), .type = &type_descr_uint16_t }, { .name = "min_data_svc_port_id", .descr = "The minimum svc_port_id that is allowed in the system", .offset = offsetof(bcmbal_interface_ind_data, min_data_svc_port_id), .type = &type_descr_uint16_t }, { .name = "transceiver_type", .descr = "The transceiver type used on an interface", .offset = offsetof(bcmbal_interface_ind_data, transceiver_type), .type = &type_descr_bcmbal_trx_type }, { .name = "ds_miss_mode", .descr = "Defines the action to take for DS unknown packets", .offset = offsetof(bcmbal_interface_ind_data, ds_miss_mode), .type = &type_descr_bcmbal_ds_miss_mode }, { .name = "mtu", .descr = "The MTU for an interface", .offset = offsetof(bcmbal_interface_ind_data, mtu), .type = &type_descr_uint16_t }, { .name = "flow_control", .descr = "Flow control enable or disable", .offset = offsetof(bcmbal_interface_ind_data, flow_control), .type = &type_descr_bcmbal_control }, { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .offset = offsetof(bcmbal_interface_ind_data, ds_tm), .type = &type_descr_uint32_t }, { .name = "us_tm", .descr = "Upstream scheduler and shaper", .offset = offsetof(bcmbal_interface_ind_data, us_tm), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_interface_ind_data = { .name = "bcmbal_interface_ind_data", .descr = "Interface Indication", .size = sizeof(bcmbal_interface_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_interface_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_interface_ind_data_fields } } };
+
+/* ==== Object: packet ==== */
+
+/* Group: packet - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_flow_id = { .name = "flow_id", .descr = "N/A for sending a packet", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_FLOW_ID, .offset = offsetof(bcmbal_packet_cfg_data, flow_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_flow_type = { .name = "flow_type", .descr = "Flow Type", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_FLOW_TYPE, .offset = offsetof(bcmbal_packet_cfg_data, flow_type), .type = &type_descr_bcmbal_flow_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_intf_id = { .name = "intf_id", .descr = "Interface ID", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_INTF_ID, .offset = offsetof(bcmbal_packet_cfg_data, intf_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_intf_type = { .name = "intf_type", .descr = "Interface Type", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_INTF_TYPE, .offset = offsetof(bcmbal_packet_cfg_data, intf_type), .type = &type_descr_bcmbal_intf_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_svc_port = { .name = "svc_port", .descr = "N/A for sending a packet", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_SVC_PORT, .offset = offsetof(bcmbal_packet_cfg_data, svc_port), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_flow_cookie = { .name = "flow_cookie", .descr = "N/A for sending a packet", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_FLOW_COOKIE, .offset = offsetof(bcmbal_packet_cfg_data, flow_cookie), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_cfg_pkt = { .name = "pkt", .descr = "Packet Data", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_CFG_ID_PKT, .offset = offsetof(bcmbal_packet_cfg_data, pkt), .type = &type_descr_bcmbal_u8_list_u32 };
+static bcmbal_apicli_prop_descr * BCM_DESCR packet_cfg_prop_array[] = { &prop_descr_packet_cfg_flow_id, &prop_descr_packet_cfg_flow_type, &prop_descr_packet_cfg_intf_id, &prop_descr_packet_cfg_intf_type, &prop_descr_packet_cfg_svc_port, &prop_descr_packet_cfg_flow_cookie, &prop_descr_packet_cfg_pkt };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_packet_cfg_data_fields[] = { { .name = "flow_id", .descr = "N/A for sending a packet", .offset = offsetof(bcmbal_packet_cfg_data, flow_id), .type = &type_descr_uint32_t }, { .name = "flow_type", .descr = "Flow Type", .offset = offsetof(bcmbal_packet_cfg_data, flow_type), .type = &type_descr_bcmbal_flow_type }, { .name = "intf_id", .descr = "Interface ID", .offset = offsetof(bcmbal_packet_cfg_data, intf_id), .type = &type_descr_uint32_t }, { .name = "intf_type", .descr = "Interface Type", .offset = offsetof(bcmbal_packet_cfg_data, intf_type), .type = &type_descr_bcmbal_intf_type }, { .name = "svc_port", .descr = "N/A for sending a packet", .offset = offsetof(bcmbal_packet_cfg_data, svc_port), .type = &type_descr_uint16_t }, { .name = "flow_cookie", .descr = "N/A for sending a packet", .offset = offsetof(bcmbal_packet_cfg_data, flow_cookie), .type = &type_descr_uint64_t }, { .name = "pkt", .descr = "Packet Data", .offset = offsetof(bcmbal_packet_cfg_data, pkt), .type = &type_descr_bcmbal_u8_list_u32 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_packet_cfg_data = { .name = "bcmbal_packet_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_packet_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_packet_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_packet_cfg_data_fields } } };
+
+/* Group: packet - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_key_reserved = { .name = "reserved", .descr = "Reserved key field", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_KEY_ID_RESERVED, .offset = offsetof(bcmbal_packet_key, reserved), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_key_packet_send_dest = { .name = "packet_send_dest", .descr = "Packet destination", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST, .offset = offsetof(bcmbal_packet_key, packet_send_dest), .type = &type_descr_bcmbal_dest };
+static bcmbal_apicli_prop_descr * BCM_DESCR packet_key_prop_array[] = { &prop_descr_packet_key_reserved, &prop_descr_packet_key_packet_send_dest };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_packet_key_fields[] = { { .name = "reserved", .descr = "Reserved key field", .offset = offsetof(bcmbal_packet_key, reserved), .type = &type_descr_uint32_t }, { .name = "packet_send_dest", .descr = "Packet destination", .offset = offsetof(bcmbal_packet_key, packet_send_dest), .type = &type_descr_bcmbal_dest } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_packet_key = { .name = "bcmbal_packet_key", .descr = "key", .size = sizeof(bcmbal_packet_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_packet_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_packet_key_fields } } };
+
+/* Group: packet - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_flow_id = { .name = "flow_id", .descr = "N/A for sending a packet", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_FLOW_ID, .offset = offsetof(bcmbal_packet_ind_data, flow_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_flow_type = { .name = "flow_type", .descr = "Flow Type", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_FLOW_TYPE, .offset = offsetof(bcmbal_packet_ind_data, flow_type), .type = &type_descr_bcmbal_flow_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_intf_id = { .name = "intf_id", .descr = "Interface ID", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_INTF_ID, .offset = offsetof(bcmbal_packet_ind_data, intf_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_intf_type = { .name = "intf_type", .descr = "Interface Type", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_INTF_TYPE, .offset = offsetof(bcmbal_packet_ind_data, intf_type), .type = &type_descr_bcmbal_intf_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_svc_port = { .name = "svc_port", .descr = "N/A for sending a packet", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_SVC_PORT, .offset = offsetof(bcmbal_packet_ind_data, svc_port), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_flow_cookie = { .name = "flow_cookie", .descr = "N/A for sending a packet", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_FLOW_COOKIE, .offset = offsetof(bcmbal_packet_ind_data, flow_cookie), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_packet_ind_pkt = { .name = "pkt", .descr = "Packet Data", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_PACKET_IND_ID_PKT, .offset = offsetof(bcmbal_packet_ind_data, pkt), .type = &type_descr_bcmbal_u8_list_u32 };
+static bcmbal_apicli_prop_descr * BCM_DESCR packet_ind_prop_array[] = { &prop_descr_packet_ind_flow_id, &prop_descr_packet_ind_flow_type, &prop_descr_packet_ind_intf_id, &prop_descr_packet_ind_intf_type, &prop_descr_packet_ind_svc_port, &prop_descr_packet_ind_flow_cookie, &prop_descr_packet_ind_pkt };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_packet_ind_data_fields[] = { { .name = "flow_id", .descr = "N/A for sending a packet", .offset = offsetof(bcmbal_packet_ind_data, flow_id), .type = &type_descr_uint32_t }, { .name = "flow_type", .descr = "Flow Type", .offset = offsetof(bcmbal_packet_ind_data, flow_type), .type = &type_descr_bcmbal_flow_type }, { .name = "intf_id", .descr = "Interface ID", .offset = offsetof(bcmbal_packet_ind_data, intf_id), .type = &type_descr_uint32_t }, { .name = "intf_type", .descr = "Interface Type", .offset = offsetof(bcmbal_packet_ind_data, intf_type), .type = &type_descr_bcmbal_intf_type }, { .name = "svc_port", .descr = "N/A for sending a packet", .offset = offsetof(bcmbal_packet_ind_data, svc_port), .type = &type_descr_uint16_t }, { .name = "flow_cookie", .descr = "N/A for sending a packet", .offset = offsetof(bcmbal_packet_ind_data, flow_cookie), .type = &type_descr_uint64_t }, { .name = "pkt", .descr = "Packet Data", .offset = offsetof(bcmbal_packet_ind_data, pkt), .type = &type_descr_bcmbal_u8_list_u32 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_packet_ind_data = { .name = "bcmbal_packet_ind_data", .descr = "Packet indication", .size = sizeof(bcmbal_packet_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_packet_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_packet_ind_data_fields } } };
+
+/* ==== Object: subscriber_terminal ==== */
+
+/* Group: subscriber_terminal - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_key_sub_term_id = { .name = "sub_term_id", .descr = "sub_term_id", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID, .offset = offsetof(bcmbal_subscriber_terminal_key, sub_term_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_key_intf_id = { .name = "intf_id", .descr = "intf_id", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID, .offset = offsetof(bcmbal_subscriber_terminal_key, intf_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR subscriber_terminal_key_prop_array[] = { &prop_descr_subscriber_terminal_key_sub_term_id, &prop_descr_subscriber_terminal_key_intf_id };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_key_fields[] = { { .name = "sub_term_id", .descr = "sub_term_id", .offset = offsetof(bcmbal_subscriber_terminal_key, sub_term_id), .type = &type_descr_uint32_t }, { .name = "intf_id", .descr = "intf_id", .offset = offsetof(bcmbal_subscriber_terminal_key, intf_id), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_key = { .name = "bcmbal_subscriber_terminal_key", .descr = "key", .size = sizeof(bcmbal_subscriber_terminal_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_subscriber_terminal_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_subscriber_terminal_key_fields } } };
+
+/* Group: subscriber_terminal - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_admin_state = { .name = "admin_state", .descr = "Administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_oper_status = { .name = "oper_status", .descr = "Operational status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_serial_number = { .name = "serial_number", .descr = "The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, serial_number), .type = &type_descr_bcmbal_serial_number };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_password = { .name = "password", .descr = "The password of a GPON subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, password), .type = &type_descr_bcmbal_password };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_registration_id = { .name = "registration_id", .descr = "ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, registration_id), .type = &type_descr_bcmbal_registration_id };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_svc_port_id = { .name = "svc_port_id", .descr = "The management service port ID (for PON, the ONU ID)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, svc_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_mac_address = { .name = "mac_address", .descr = "The Ethernet MAC address of an EPON subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, mac_address), .type = &type_descr_bcmos_mac_address };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_ds_tm = { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, ds_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_us_tm = { .name = "us_tm", .descr = "Upstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, us_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_svc_port_id_list = { .name = "svc_port_id_list", .descr = "A list of bearer traffic svc_port_ids associated with this subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, svc_port_id_list), .type = &type_descr_bcmbal_service_port_id_list_u8 };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_cfg_agg_port_id_list = { .name = "agg_port_id_list", .descr = "A list of aggr_port_ids associated with this subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST, .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, agg_port_id_list), .type = &type_descr_bcmbal_aggregation_port_id_list_u8 };
+static bcmbal_apicli_prop_descr * BCM_DESCR subscriber_terminal_cfg_prop_array[] = { &prop_descr_subscriber_terminal_cfg_admin_state, &prop_descr_subscriber_terminal_cfg_oper_status, &prop_descr_subscriber_terminal_cfg_serial_number, &prop_descr_subscriber_terminal_cfg_password, &prop_descr_subscriber_terminal_cfg_registration_id, &prop_descr_subscriber_terminal_cfg_svc_port_id, &prop_descr_subscriber_terminal_cfg_mac_address, &prop_descr_subscriber_terminal_cfg_ds_tm, &prop_descr_subscriber_terminal_cfg_us_tm, &prop_descr_subscriber_terminal_cfg_svc_port_id_list, &prop_descr_subscriber_terminal_cfg_agg_port_id_list };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_cfg_data_fields[] = { { .name = "admin_state", .descr = "Administrative state", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Operational status", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "serial_number", .descr = "The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, serial_number), .type = &type_descr_bcmbal_serial_number }, { .name = "password", .descr = "The password of a GPON subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, password), .type = &type_descr_bcmbal_password }, { .name = "registration_id", .descr = "ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, registration_id), .type = &type_descr_bcmbal_registration_id }, { .name = "svc_port_id", .descr = "The management service port ID (for PON, the ONU ID)", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, svc_port_id), .type = &type_descr_uint16_t }, { .name = "mac_address", .descr = "The Ethernet MAC address of an EPON subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, mac_address), .type = &type_descr_bcmos_mac_address }, { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, ds_tm), .type = &type_descr_uint32_t }, { .name = "us_tm", .descr = "Upstream scheduler and shaper", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, us_tm), .type = &type_descr_uint32_t }, { .name = "svc_port_id_list", .descr = "A list of bearer traffic svc_port_ids associated with this subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, svc_port_id_list), .type = &type_descr_bcmbal_service_port_id_list_u8 }, { .name = "agg_port_id_list", .descr = "A list of aggr_port_ids associated with this subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_cfg_data, agg_port_id_list), .type = &type_descr_bcmbal_aggregation_port_id_list_u8 } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_cfg_data = { .name = "bcmbal_subscriber_terminal_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_subscriber_terminal_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_subscriber_terminal_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_subscriber_terminal_cfg_data_fields } } };
+
+/* Group: subscriber_terminal - stat */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_stat_rx_packets = { .name = "rx_packets", .descr = "Received packets on specified object", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS, .offset = offsetof(bcmbal_subscriber_terminal_stat_data, rx_packets), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_stat_rx_bytes = { .name = "rx_bytes", .descr = "Received bytes on specified object", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES, .offset = offsetof(bcmbal_subscriber_terminal_stat_data, rx_bytes), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_stat_tx_packets = { .name = "tx_packets", .descr = "Transmitted packets on specified object", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS, .offset = offsetof(bcmbal_subscriber_terminal_stat_data, tx_packets), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_stat_tx_bytes = { .name = "tx_bytes", .descr = "Transmittted bytes on specified object", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES, .offset = offsetof(bcmbal_subscriber_terminal_stat_data, tx_bytes), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR subscriber_terminal_stat_prop_array[] = { &prop_descr_subscriber_terminal_stat_rx_packets, &prop_descr_subscriber_terminal_stat_rx_bytes, &prop_descr_subscriber_terminal_stat_tx_packets, &prop_descr_subscriber_terminal_stat_tx_bytes };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_stat_data_fields[] = { { .name = "rx_packets", .descr = "Received packets on specified object", .offset = offsetof(bcmbal_subscriber_terminal_stat_data, rx_packets), .type = &type_descr_uint64_t }, { .name = "rx_bytes", .descr = "Received bytes on specified object", .offset = offsetof(bcmbal_subscriber_terminal_stat_data, rx_bytes), .type = &type_descr_uint64_t }, { .name = "tx_packets", .descr = "Transmitted packets on specified object", .offset = offsetof(bcmbal_subscriber_terminal_stat_data, tx_packets), .type = &type_descr_uint64_t }, { .name = "tx_bytes", .descr = "Transmittted bytes on specified object", .offset = offsetof(bcmbal_subscriber_terminal_stat_data, tx_bytes), .type = &type_descr_uint64_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_stat_data = { .name = "bcmbal_subscriber_terminal_stat_data", .descr = "stat", .size = sizeof(bcmbal_subscriber_terminal_stat_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_subscriber_terminal_stat_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_subscriber_terminal_stat_data_fields } } };
+
+/* Group: subscriber_terminal - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_admin_state = { .name = "admin_state", .descr = "Current administrative state", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, admin_state), .type = &type_descr_bcmbal_state };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_oper_status = { .name = "oper_status", .descr = "Current operational status", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, oper_status), .type = &type_descr_bcmbal_status };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_serial_number = { .name = "serial_number", .descr = "The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, serial_number), .type = &type_descr_bcmbal_serial_number };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_password = { .name = "password", .descr = "The password of a GPON subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, password), .type = &type_descr_bcmbal_password };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_registration_id = { .name = "registration_id", .descr = "ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, registration_id), .type = &type_descr_bcmbal_registration_id };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_svc_port_id = { .name = "svc_port_id", .descr = "The service port ID (for PON, the ONU ID)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, svc_port_id), .type = &type_descr_uint16_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_mac_address = { .name = "mac_address", .descr = "The Ethernet MAC address of an epon subscriber terminal", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, mac_address), .type = &type_descr_bcmos_mac_address };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_ds_tm = { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, ds_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_subscriber_terminal_ind_us_tm = { .name = "us_tm", .descr = "Upstream scheduler and shaper", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM, .offset = offsetof(bcmbal_subscriber_terminal_ind_data, us_tm), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR subscriber_terminal_ind_prop_array[] = { &prop_descr_subscriber_terminal_ind_admin_state, &prop_descr_subscriber_terminal_ind_oper_status, &prop_descr_subscriber_terminal_ind_serial_number, &prop_descr_subscriber_terminal_ind_password, &prop_descr_subscriber_terminal_ind_registration_id, &prop_descr_subscriber_terminal_ind_svc_port_id, &prop_descr_subscriber_terminal_ind_mac_address, &prop_descr_subscriber_terminal_ind_ds_tm, &prop_descr_subscriber_terminal_ind_us_tm };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_ind_data_fields[] = { { .name = "admin_state", .descr = "Current administrative state", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, admin_state), .type = &type_descr_bcmbal_state }, { .name = "oper_status", .descr = "Current operational status", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, oper_status), .type = &type_descr_bcmbal_status }, { .name = "serial_number", .descr = "The serial number of an ITU PON (GPON/XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, serial_number), .type = &type_descr_bcmbal_serial_number }, { .name = "password", .descr = "The password of a GPON subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, password), .type = &type_descr_bcmbal_password }, { .name = "registration_id", .descr = "ONU registration ID of an ITU PON (XG-PON1/XGS-PON/NG-PON2) subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, registration_id), .type = &type_descr_bcmbal_registration_id }, { .name = "svc_port_id", .descr = "The service port ID (for PON, the ONU ID)", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, svc_port_id), .type = &type_descr_uint16_t }, { .name = "mac_address", .descr = "The Ethernet MAC address of an epon subscriber terminal", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, mac_address), .type = &type_descr_bcmos_mac_address }, { .name = "ds_tm", .descr = "Downstream scheduler and shaper", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, ds_tm), .type = &type_descr_uint32_t }, { .name = "us_tm", .descr = "Upstream scheduler and shaper", .offset = offsetof(bcmbal_subscriber_terminal_ind_data, us_tm), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_subscriber_terminal_ind_data = { .name = "bcmbal_subscriber_terminal_ind_data", .descr = "Subscriber Terminal Indication", .size = sizeof(bcmbal_subscriber_terminal_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_subscriber_terminal_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_subscriber_terminal_ind_data_fields } } };
+
+/* ==== Object: tm_queue ==== */
+
+/* Group: tm_queue - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_key_sched_id = { .name = "sched_id", .descr = "Scheduler that owns the queue", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID, .offset = offsetof(bcmbal_tm_queue_key, sched_id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_key_sched_dir = { .name = "sched_dir", .descr = "sched dir", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR, .offset = offsetof(bcmbal_tm_queue_key, sched_dir), .type = &type_descr_bcmbal_tm_sched_dir };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_key_id = { .name = "id", .descr = "Queue id", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_KEY_ID_ID, .offset = offsetof(bcmbal_tm_queue_key, id), .type = &type_descr_uint8_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_queue_key_prop_array[] = { &prop_descr_tm_queue_key_sched_id, &prop_descr_tm_queue_key_sched_dir, &prop_descr_tm_queue_key_id };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_queue_key_fields[] = { { .name = "sched_id", .descr = "Scheduler that owns the queue", .offset = offsetof(bcmbal_tm_queue_key, sched_id), .type = &type_descr_uint32_t }, { .name = "sched_dir", .descr = "sched dir", .offset = offsetof(bcmbal_tm_queue_key, sched_dir), .type = &type_descr_bcmbal_tm_sched_dir }, { .name = "id", .descr = "Queue id", .offset = offsetof(bcmbal_tm_queue_key, id), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_key = { .name = "bcmbal_tm_queue_key", .descr = "key", .size = sizeof(bcmbal_tm_queue_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_queue_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_queue_key_fields } } };
+
+/* Group: tm_queue - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_cfg_priority = { .name = "priority", .descr = "Scheduling priority", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_CFG_ID_PRIORITY, .offset = offsetof(bcmbal_tm_queue_cfg_data, priority), .type = &type_descr_uint8_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_cfg_weight = { .name = "weight", .descr = "Scheduling weight", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_CFG_ID_WEIGHT, .offset = offsetof(bcmbal_tm_queue_cfg_data, weight), .type = &type_descr_uint8_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_cfg_rate = { .name = "rate", .descr = "Rate shaping parameters", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_CFG_ID_RATE, .offset = offsetof(bcmbal_tm_queue_cfg_data, rate), .type = &type_descr_bcmbal_tm_shaping };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_cfg_bac = { .name = "bac", .descr = "Buffer admission control", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_CFG_ID_BAC, .offset = offsetof(bcmbal_tm_queue_cfg_data, bac), .type = &type_descr_bcmbal_tm_bac };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_cfg_creation_mode = { .name = "creation_mode", .descr = "Creation mode", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE, .offset = offsetof(bcmbal_tm_queue_cfg_data, creation_mode), .type = &type_descr_bcmbal_tm_creation_mode };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_cfg_ref_count = { .name = "ref_count", .descr = "reference count (flows)", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT, .offset = offsetof(bcmbal_tm_queue_cfg_data, ref_count), .type = &type_descr_uint8_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_queue_cfg_prop_array[] = { &prop_descr_tm_queue_cfg_priority, &prop_descr_tm_queue_cfg_weight, &prop_descr_tm_queue_cfg_rate, &prop_descr_tm_queue_cfg_bac, &prop_descr_tm_queue_cfg_creation_mode, &prop_descr_tm_queue_cfg_ref_count };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_queue_cfg_data_fields[] = { { .name = "priority", .descr = "Scheduling priority", .offset = offsetof(bcmbal_tm_queue_cfg_data, priority), .type = &type_descr_uint8_t }, { .name = "weight", .descr = "Scheduling weight", .offset = offsetof(bcmbal_tm_queue_cfg_data, weight), .type = &type_descr_uint8_t }, { .name = "rate", .descr = "Rate shaping parameters", .offset = offsetof(bcmbal_tm_queue_cfg_data, rate), .type = &type_descr_bcmbal_tm_shaping }, { .name = "bac", .descr = "Buffer admission control", .offset = offsetof(bcmbal_tm_queue_cfg_data, bac), .type = &type_descr_bcmbal_tm_bac }, { .name = "creation_mode", .descr = "Creation mode", .offset = offsetof(bcmbal_tm_queue_cfg_data, creation_mode), .type = &type_descr_bcmbal_tm_creation_mode }, { .name = "ref_count", .descr = "reference count (flows)", .offset = offsetof(bcmbal_tm_queue_cfg_data, ref_count), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_cfg_data = { .name = "bcmbal_tm_queue_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_tm_queue_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_queue_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_queue_cfg_data_fields } } };
+
+/* Group: tm_queue - stat */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_stat_packets_ok = { .name = "packets_ok", .descr = "Packets transmitted succewssfully", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK, .offset = offsetof(bcmbal_tm_queue_stat_data, packets_ok), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_stat_bytes_ok = { .name = "bytes_ok", .descr = "Bytes transmitted successfully", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK, .offset = offsetof(bcmbal_tm_queue_stat_data, bytes_ok), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_stat_packets_discarded = { .name = "packets_discarded", .descr = "Packets discarded", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED, .offset = offsetof(bcmbal_tm_queue_stat_data, packets_discarded), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_stat_bytes_discarded = { .name = "bytes_discarded", .descr = "Bytes discarded", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED, .offset = offsetof(bcmbal_tm_queue_stat_data, bytes_discarded), .type = &type_descr_uint64_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_queue_stat_prop_array[] = { &prop_descr_tm_queue_stat_packets_ok, &prop_descr_tm_queue_stat_bytes_ok, &prop_descr_tm_queue_stat_packets_discarded, &prop_descr_tm_queue_stat_bytes_discarded };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_queue_stat_data_fields[] = { { .name = "packets_ok", .descr = "Packets transmitted succewssfully", .offset = offsetof(bcmbal_tm_queue_stat_data, packets_ok), .type = &type_descr_uint64_t }, { .name = "bytes_ok", .descr = "Bytes transmitted successfully", .offset = offsetof(bcmbal_tm_queue_stat_data, bytes_ok), .type = &type_descr_uint64_t }, { .name = "packets_discarded", .descr = "Packets discarded", .offset = offsetof(bcmbal_tm_queue_stat_data, packets_discarded), .type = &type_descr_uint64_t }, { .name = "bytes_discarded", .descr = "Bytes discarded", .offset = offsetof(bcmbal_tm_queue_stat_data, bytes_discarded), .type = &type_descr_uint64_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_stat_data = { .name = "bcmbal_tm_queue_stat_data", .descr = "stat", .size = sizeof(bcmbal_tm_queue_stat_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_queue_stat_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_queue_stat_data_fields } } };
+
+/* Group: tm_queue - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_queue_ind_ret = { .name = "ret", .descr = "ret", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_QUEUE_IND_ID_RET, .offset = offsetof(bcmbal_tm_queue_ind_data, ret), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_queue_ind_prop_array[] = { &prop_descr_tm_queue_ind_ret };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_queue_ind_data_fields[] = { { .name = "ret", .descr = "ret", .offset = offsetof(bcmbal_tm_queue_ind_data, ret), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_queue_ind_data = { .name = "bcmbal_tm_queue_ind_data", .descr = "Tm Queue Indication", .size = sizeof(bcmbal_tm_queue_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_queue_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_queue_ind_data_fields } } };
+
+/* ==== Object: tm_sched ==== */
+
+/* Group: tm_sched - key */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_key_dir = { .name = "dir", .descr = "Traffic direction", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_KEY_ID_DIR, .offset = offsetof(bcmbal_tm_sched_key, dir), .type = &type_descr_bcmbal_tm_sched_dir };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_key_id = { .name = "id", .descr = "ID", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_KEY_ID_ID, .offset = offsetof(bcmbal_tm_sched_key, id), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_sched_key_prop_array[] = { &prop_descr_tm_sched_key_dir, &prop_descr_tm_sched_key_id };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_key_fields[] = { { .name = "dir", .descr = "Traffic direction", .offset = offsetof(bcmbal_tm_sched_key, dir), .type = &type_descr_bcmbal_tm_sched_dir }, { .name = "id", .descr = "ID", .offset = offsetof(bcmbal_tm_sched_key, id), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_key = { .name = "bcmbal_tm_sched_key", .descr = "key", .size = sizeof(bcmbal_tm_sched_key), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_key_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_key_fields } } };
+
+/* Group: tm_sched - cfg */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_owner = { .name = "owner", .descr = "owner", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_OWNER, .offset = offsetof(bcmbal_tm_sched_cfg_data, owner), .type = &type_descr_bcmbal_tm_sched_owner };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_sched_type = { .name = "sched_type", .descr = "Scheduler type", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE, .offset = offsetof(bcmbal_tm_sched_cfg_data, sched_type), .type = &type_descr_bcmbal_tm_sched_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_sched_parent = { .name = "sched_parent", .descr = "Scheduling parameters for parent scheduler", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT, .offset = offsetof(bcmbal_tm_sched_cfg_data, sched_parent), .type = &type_descr_bcmbal_tm_sched_parent };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_sched_child_type = { .name = "sched_child_type", .descr = "Scheduling level for children tm ", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE, .offset = offsetof(bcmbal_tm_sched_cfg_data, sched_child_type), .type = &type_descr_bcmbal_tm_sched_child_type };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_rate = { .name = "rate", .descr = "Rate shaping parameters", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_RATE, .offset = offsetof(bcmbal_tm_sched_cfg_data, rate), .type = &type_descr_bcmbal_tm_shaping };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_tcont_sla = { .name = "tcont_sla", .descr = "Additional SLA parameters for agg_port owner", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA, .offset = offsetof(bcmbal_tm_sched_cfg_data, tcont_sla), .type = &type_descr_bcmbal_tm_tcont_sla };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_creation_mode = { .name = "creation_mode", .descr = "Creation mode", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE, .offset = offsetof(bcmbal_tm_sched_cfg_data, creation_mode), .type = &type_descr_bcmbal_tm_creation_mode };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_queues = { .name = "queues", .descr = "Subsidiary queues", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_TM_SCHED_CFG_ID_QUEUES, .offset = offsetof(bcmbal_tm_sched_cfg_data, queues), .type = &type_descr_bcmbal_tm_queue_id_list_u8 };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_sub_scheds = { .name = "sub_scheds", .descr = "Subsidiary schedulers", .access = BCMBAL_APICLI_PROP_ACCESS_ID_R, .property = BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS, .offset = offsetof(bcmbal_tm_sched_cfg_data, sub_scheds), .type = &type_descr_bcmbal_tm_sched_id_list_u8 };
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_cfg_num_priorities = { .name = "num_priorities", .descr = "Max number of strict priority scheduling elements", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES, .offset = offsetof(bcmbal_tm_sched_cfg_data, num_priorities), .type = &type_descr_uint8_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_sched_cfg_prop_array[] = { &prop_descr_tm_sched_cfg_owner, &prop_descr_tm_sched_cfg_sched_type, &prop_descr_tm_sched_cfg_sched_parent, &prop_descr_tm_sched_cfg_sched_child_type, &prop_descr_tm_sched_cfg_rate, &prop_descr_tm_sched_cfg_tcont_sla, &prop_descr_tm_sched_cfg_creation_mode, &prop_descr_tm_sched_cfg_queues, &prop_descr_tm_sched_cfg_sub_scheds, &prop_descr_tm_sched_cfg_num_priorities };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_cfg_data_fields[] = { { .name = "owner", .descr = "owner", .offset = offsetof(bcmbal_tm_sched_cfg_data, owner), .type = &type_descr_bcmbal_tm_sched_owner }, { .name = "sched_type", .descr = "Scheduler type", .offset = offsetof(bcmbal_tm_sched_cfg_data, sched_type), .type = &type_descr_bcmbal_tm_sched_type }, { .name = "sched_parent", .descr = "Scheduling parameters for parent scheduler", .offset = offsetof(bcmbal_tm_sched_cfg_data, sched_parent), .type = &type_descr_bcmbal_tm_sched_parent }, { .name = "sched_child_type", .descr = "Scheduling level for children tm ", .offset = offsetof(bcmbal_tm_sched_cfg_data, sched_child_type), .type = &type_descr_bcmbal_tm_sched_child_type }, { .name = "rate", .descr = "Rate shaping parameters", .offset = offsetof(bcmbal_tm_sched_cfg_data, rate), .type = &type_descr_bcmbal_tm_shaping }, { .name = "tcont_sla", .descr = "Additional SLA parameters for agg_port owner", .offset = offsetof(bcmbal_tm_sched_cfg_data, tcont_sla), .type = &type_descr_bcmbal_tm_tcont_sla }, { .name = "creation_mode", .descr = "Creation mode", .offset = offsetof(bcmbal_tm_sched_cfg_data, creation_mode), .type = &type_descr_bcmbal_tm_creation_mode }, { .name = "queues", .descr = "Subsidiary queues", .offset = offsetof(bcmbal_tm_sched_cfg_data, queues), .type = &type_descr_bcmbal_tm_queue_id_list_u8 }, { .name = "sub_scheds", .descr = "Subsidiary schedulers", .offset = offsetof(bcmbal_tm_sched_cfg_data, sub_scheds), .type = &type_descr_bcmbal_tm_sched_id_list_u8 }, { .name = "num_priorities", .descr = "Max number of strict priority scheduling elements", .offset = offsetof(bcmbal_tm_sched_cfg_data, num_priorities), .type = &type_descr_uint8_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_cfg_data = { .name = "bcmbal_tm_sched_cfg_data", .descr = "cfg", .size = sizeof(bcmbal_tm_sched_cfg_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_cfg_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_cfg_data_fields } } };
+
+/* Group: tm_sched - ind */
+static bcmbal_apicli_prop_descr BCM_DESCR prop_descr_tm_sched_ind_ret = { .name = "ret", .descr = "ret", .access = BCMBAL_APICLI_PROP_ACCESS_ID_RW, .property = BCMBAL_TM_SCHED_IND_ID_RET, .offset = offsetof(bcmbal_tm_sched_ind_data, ret), .type = &type_descr_uint32_t };
+static bcmbal_apicli_prop_descr * BCM_DESCR tm_sched_ind_prop_array[] = { &prop_descr_tm_sched_ind_ret };
+static bcmbal_apicli_field_descr BCM_DESCR type_descr_bcmbal_tm_sched_ind_data_fields[] = { { .name = "ret", .descr = "ret", .offset = offsetof(bcmbal_tm_sched_ind_data, ret), .type = &type_descr_uint32_t } };
+static bcmbal_apicli_type_descr BCM_DESCR type_descr_bcmbal_tm_sched_ind_data = { .name = "bcmbal_tm_sched_ind_data", .descr = "Tm Sched Indication", .size = sizeof(bcmbal_tm_sched_ind_data), .base_type = BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, .x = { .s = { .num_fields = sizeof(type_descr_bcmbal_tm_sched_ind_data_fields) / sizeof(bcmbal_apicli_field_descr), .fields = type_descr_bcmbal_tm_sched_ind_data_fields } } };
+
+/* ==== API Helper Function Implementations ==== */
+bcmos_errno bcmbal_apicli_object_struct_size(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, uint32_t *key_size, uint32_t *key_offset, uint32_t *data_size, uint32_t *data_offset)
+{
+ if (((key_size == NULL) || (key_offset == NULL)) || ((data_size == NULL) || (data_offset == NULL)))
+ {
+ return BCM_ERR_RANGE;
+ }
+
+ switch (obj)
+ {
+ case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_access_terminal_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_access_terminal_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_access_terminal_key);
+ *key_offset = offsetof(bcmbal_access_terminal_cfg, key);
+ *data_size = sizeof(bcmbal_access_terminal_cfg_data);
+ *data_offset = offsetof(bcmbal_access_terminal_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_ACCESS_TERMINAL_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_access_terminal_key);
+ *key_offset = offsetof(bcmbal_access_terminal_ind, key);
+ *data_size = sizeof(bcmbal_access_terminal_ind_data);
+ *data_offset = offsetof(bcmbal_access_terminal_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_FLOW:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_flow_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_flow_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_flow_key);
+ *key_offset = offsetof(bcmbal_flow_cfg, key);
+ *data_size = sizeof(bcmbal_flow_cfg_data);
+ *data_offset = offsetof(bcmbal_flow_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_flow_key);
+ *key_offset = offsetof(bcmbal_flow_stat, key);
+ *data_size = sizeof(bcmbal_flow_stat_data);
+ *data_offset = offsetof(bcmbal_flow_stat, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_FLOW_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_flow_key);
+ *key_offset = offsetof(bcmbal_flow_ind, key);
+ *data_size = sizeof(bcmbal_flow_ind_data);
+ *data_offset = offsetof(bcmbal_flow_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_GROUP:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_group_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_group_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_group_key);
+ *key_offset = offsetof(bcmbal_group_cfg, key);
+ *data_size = sizeof(bcmbal_group_cfg_data);
+ *data_offset = offsetof(bcmbal_group_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_INTERFACE:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_interface_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_interface_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_interface_key);
+ *key_offset = offsetof(bcmbal_interface_cfg, key);
+ *data_size = sizeof(bcmbal_interface_cfg_data);
+ *data_offset = offsetof(bcmbal_interface_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_interface_key);
+ *key_offset = offsetof(bcmbal_interface_stat, key);
+ *data_size = sizeof(bcmbal_interface_stat_data);
+ *data_offset = offsetof(bcmbal_interface_stat, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_INTERFACE_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_interface_key);
+ *key_offset = offsetof(bcmbal_interface_ind, key);
+ *data_size = sizeof(bcmbal_interface_ind_data);
+ *data_offset = offsetof(bcmbal_interface_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_PACKET:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_packet_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_packet_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_packet_key);
+ *key_offset = offsetof(bcmbal_packet_cfg, key);
+ *data_size = sizeof(bcmbal_packet_cfg_data);
+ *data_offset = offsetof(bcmbal_packet_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_PACKET_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_packet_key);
+ *key_offset = offsetof(bcmbal_packet_ind, key);
+ *data_size = sizeof(bcmbal_packet_ind_data);
+ *data_offset = offsetof(bcmbal_packet_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_subscriber_terminal_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_subscriber_terminal_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_subscriber_terminal_key);
+ *key_offset = offsetof(bcmbal_subscriber_terminal_cfg, key);
+ *data_size = sizeof(bcmbal_subscriber_terminal_cfg_data);
+ *data_offset = offsetof(bcmbal_subscriber_terminal_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_subscriber_terminal_key);
+ *key_offset = offsetof(bcmbal_subscriber_terminal_stat, key);
+ *data_size = sizeof(bcmbal_subscriber_terminal_stat_data);
+ *data_offset = offsetof(bcmbal_subscriber_terminal_stat, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_subscriber_terminal_key);
+ *key_offset = offsetof(bcmbal_subscriber_terminal_ind, key);
+ *data_size = sizeof(bcmbal_subscriber_terminal_ind_data);
+ *data_offset = offsetof(bcmbal_subscriber_terminal_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_TM_QUEUE:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_tm_queue_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_tm_queue_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_tm_queue_key);
+ *key_offset = offsetof(bcmbal_tm_queue_cfg, key);
+ *data_size = sizeof(bcmbal_tm_queue_cfg_data);
+ *data_offset = offsetof(bcmbal_tm_queue_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_tm_queue_key);
+ *key_offset = offsetof(bcmbal_tm_queue_stat, key);
+ *data_size = sizeof(bcmbal_tm_queue_stat_data);
+ *data_offset = offsetof(bcmbal_tm_queue_stat, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_TM_QUEUE_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_tm_queue_key);
+ *key_offset = offsetof(bcmbal_tm_queue_ind, key);
+ *data_size = sizeof(bcmbal_tm_queue_ind_data);
+ *data_offset = offsetof(bcmbal_tm_queue_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_TM_SCHED:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_tm_sched_key);
+ *key_offset = 0;
+ *data_size = sizeof(bcmbal_tm_sched_key);
+ *data_offset = 0;
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *key_size = sizeof(bcmbal_tm_sched_key);
+ *key_offset = offsetof(bcmbal_tm_sched_cfg, key);
+ *data_size = sizeof(bcmbal_tm_sched_cfg_data);
+ *data_offset = offsetof(bcmbal_tm_sched_cfg, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_TM_SCHED_AUTO_ID_IND:
+ *key_size = sizeof(bcmbal_tm_sched_key);
+ *key_offset = offsetof(bcmbal_tm_sched_ind, key);
+ *data_size = sizeof(bcmbal_tm_sched_ind_data);
+ *data_offset = offsetof(bcmbal_tm_sched_ind, data);
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ return BCM_ERR_INTERNAL; /**< should never happen. */
+}
+
+bcmos_errno bcmbal_apicli_object_subgroup_name(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, const char **name, const char **descr)
+{
+ switch (obj)
+ {
+ case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_ACCESS_TERMINAL_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Access Terminal Indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_FLOW:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "stat";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "stat";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_FLOW_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Flow Indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_GROUP:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_INTERFACE:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "stat";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "stat";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_INTERFACE_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Interface Indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_PACKET:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_PACKET_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Packet indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "stat";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "stat";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Subscriber Terminal Indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_TM_QUEUE:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "stat";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "stat";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_TM_QUEUE_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Tm Queue Indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_OBJ_ID_TM_SCHED:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "key";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "key";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ if (name != NULL)
+ {
+ *name = "cfg";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "cfg";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_TM_SCHED_AUTO_ID_IND:
+ if (name != NULL)
+ {
+ *name = "ind";
+ }
+
+ if (descr != NULL)
+ {
+ *descr = "Tm Sched Indication";
+ }
+
+ return BCM_ERR_OK;
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ default:
+ return BCM_ERR_RANGE;
+ }
+
+ return BCM_ERR_INTERNAL; /**< should never happen. */
+}
+
+static bcmbal_apicli_prop_descr **obj_get_prop_array(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, uint32_t *size)
+{
+ switch (obj)
+ {
+ case BCMBAL_OBJ_ID_ACCESS_TERMINAL:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(access_terminal_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return access_terminal_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(access_terminal_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return access_terminal_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_ACCESS_TERMINAL_AUTO_ID_IND:
+ *size = sizeof(access_terminal_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return access_terminal_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_FLOW:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(flow_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return flow_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(flow_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return flow_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(flow_stat_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return flow_stat_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_FLOW_AUTO_ID_IND:
+ *size = sizeof(flow_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return flow_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_GROUP:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(group_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return group_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(group_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return group_cfg_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_INTERFACE:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(interface_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return interface_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(interface_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return interface_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(interface_stat_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return interface_stat_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_INTERFACE_AUTO_ID_IND:
+ *size = sizeof(interface_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return interface_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_PACKET:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(packet_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return packet_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(packet_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return packet_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_PACKET_AUTO_ID_IND:
+ *size = sizeof(packet_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return packet_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(subscriber_terminal_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return subscriber_terminal_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(subscriber_terminal_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return subscriber_terminal_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(subscriber_terminal_stat_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return subscriber_terminal_stat_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_SUBSCRIBER_TERMINAL_AUTO_ID_IND:
+ *size = sizeof(subscriber_terminal_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return subscriber_terminal_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_TM_QUEUE:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(tm_queue_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_queue_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(tm_queue_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_queue_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_STAT:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(tm_queue_stat_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_queue_stat_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_TM_QUEUE_AUTO_ID_IND:
+ *size = sizeof(tm_queue_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_queue_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ case BCMBAL_OBJ_ID_TM_SCHED:
+ switch (group)
+ {
+ case BCMBAL_MGT_GROUP_KEY:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(tm_sched_key_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_sched_key_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_CFG:
+ switch (subgroup)
+ {
+ case 0:
+ *size = sizeof(tm_sched_cfg_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_sched_cfg_prop_array;
+ default:
+ break;
+ }
+
+ case BCMBAL_MGT_GROUP_AUTO:
+ switch (subgroup)
+ {
+ case BCMBAL_TM_SCHED_AUTO_ID_IND:
+ *size = sizeof(tm_sched_ind_prop_array) / sizeof(bcmbal_apicli_prop_descr *);
+ return tm_sched_ind_prop_array;
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+bcmos_errno bcmbal_apicli_object_name(bcmbal_obj_id obj, const char **name, const char **descr)
+{
+ if (obj >= BCMBAL_OBJ_ID__NUM_OF)
+ {
+ return BCM_ERR_RANGE;
+ }
+
+ if (object_name[obj] == NULL)
+ {
+ return BCM_ERR_NOENT;
+ }
+
+ if (name != NULL)
+ {
+ *name = object_name[obj];
+ }
+
+ if (descr != NULL)
+ {
+ *descr = object_descr[obj];
+ }
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcmbal_apicli_object_property(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, uint16_t prop, const bcmbal_apicli_prop_descr **descr)
+{
+ bcmbal_apicli_prop_descr **prop_array = NULL;
+ uint32_t prop_array_size = 0;
+ if (descr == NULL)
+ {
+ return BCM_ERR_PARM;
+ }
+
+ prop_array = obj_get_prop_array(obj, group, subgroup, &prop_array_size);
+ if ((prop_array == NULL) || (prop >= prop_array_size))
+ {
+ return BCM_ERR_RANGE;
+ }
+
+ if (prop_array[prop] == NULL)
+ {
+ return BCM_ERR_NOENT;
+ }
+
+ *descr = prop_array[prop];
+ return BCM_ERR_OK;
+}
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli_helpers.h b/bal_release/src/lib/libbalapicli/bal_api_cli_helpers.h
new file mode 100644
index 0000000..07e922a
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli_helpers.h
@@ -0,0 +1,221 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(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 BCMBAL_APICLI_HELPERS_H_
+#define BCMBAL_APICLI_HELPERS_H_
+
+#include <bcmcli.h>
+#include <bal_api.h>
+#include "bal_api_cli_types.h"
+
+/* Mac name length */
+#define BCMBAL_APICLI_MAX_PARM_NAME_LENGTH BCMCLI_MAX_SEARCH_SUBSTR_LENGTH
+
+/* Max help string length */
+#define BCMBAL_APICLI_MAX_PARM_HELP_LENGTH 128
+
+typedef enum bcmbal_apicli_field_descr_flags
+{
+ BCMBAL_APICLI_FIELD_DESCR_FLAGS_NONE = 0,
+ BCMBAL_APICLI_FIELD_DESCR_FLAGS_PRESENCE_MASK = (1 << 0) /* field is a 'presence mask' for a structure */
+} bcmbal_apicli_field_descr_flags;
+
+typedef struct bcmbal_apicli_type_descr bcmbal_apicli_type_descr;
+
+/* Structure field descriptor */
+typedef struct bcmbal_apicli_field_descr
+{
+ const char *name; /* Field name */
+ const char *descr; /* Field description */
+ const char *cli_name; /* Short CLI name. can be missing */
+ bcmbal_apicli_type_descr *type; /* Field type */
+ uint16_t offset; /* Offset from the beginning of the type structure */
+ bcmbal_apicli_field_descr_flags flags;
+} bcmbal_apicli_field_descr;
+
+/* Data type descriptor */
+struct bcmbal_apicli_type_descr
+{
+ const char *name; /* Type name */
+ const char *descr; /* Type description. can be missing */
+ const char *cli_name; /* Short CLI name. can be missing */
+ bcmbal_apicli_base_type_id base_type; /* Base type: snum, unum, string, ip, enum, etc. */
+ uint32_t min_val; /* Min value for range check */
+ uint32_t max_val; /* Max value for range check */
+ uint16_t size; /* Size */
+
+ /* The following union is qualified by the base_type and contains additional
+ * info for array, enum, struct, union */
+ union
+ {
+ bcmcli_enum_val *e; /* enum value array Contains num_elements+1 values. The last value has name=NULL */
+ struct
+ {
+ uint16_t num_fields; /* number of elements in the following structure */
+ bcmbal_apicli_field_descr *fields; /* Structure field array. Contains num_elements values */
+ } s;
+ struct
+ {
+ uint16_t num_common_fields; /* number of non-union fields at the start of the struct */
+ bcmbal_apicli_field_descr *common_fields; /* common field array. Contains num_elements values */
+ uint16_t classifier_idx; /* index of the classifier field within common_fields */
+ bcmbal_apicli_field_descr *union_fields; /* sub-struct fields under the union (name == NULL if no fields present)
+ (one per enum entry in the classifier type, plus one for default) */
+ } u;
+ struct
+ {
+ bcmbal_apicli_type_descr *elem_type; /* Array element type */
+ uint8_t len_size; /* Byte width of array length field (at start of struct) */
+ uint16_t max_size; /* Max array size */
+ } arr_dyn;
+ struct
+ {
+ bcmbal_apicli_type_descr *elem_type; /* Array element type */
+ uint16_t size; /* Fixed array size */
+ } arr_fixed;
+ } x;
+};
+
+/* Property descriptor.
+ * The 1st 5 fields are exactly the same as in bcmbal_apicli_field_descr
+ * ToDo: replace with bcmbal_apicli_field_descr substructure.
+ * Requires changes in code generator
+ */
+typedef struct
+{
+ const char *name; /* C name */
+ const char *descr; /* Property description */
+ const char *cli_name; /* CLI name */
+ bcmbal_apicli_type_descr *type; /* Type reference */
+ uint16_t offset; /* Offset in generated per-group structure */
+ uint16_t property; /* Property id in per-object management group */
+ bcmbal_apicli_prop_access_id access; /* Access */
+} bcmbal_apicli_prop_descr;
+
+/* All APIs return
+ * BCM_ERR_OK - ok
+ * BCM_ERR_NOENT - if id is in range, but doesn't correspond to any value (a hole)
+ * BCM_ERR_RANGE - id is out of range
+ */
+
+/* Get object name by id */
+bcmos_errno bcmbal_apicli_object_name(bcmbal_obj_id obj, const char **name, const char **descr);
+
+/* Get object structure size */
+bcmos_errno bcmbal_apicli_object_struct_size(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, uint32_t *key_size, uint32_t *key_offset, uint32_t *data_size, uint32_t *data_offset);
+
+/* Get object subgroup (e.g. specific indication) name and description */
+bcmos_errno bcmbal_apicli_object_subgroup_name(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, const char **name, const char **descr);
+
+/* Get property by object, mgt_group, subgroup (e.g. specific indication), property_id */
+bcmos_errno bcmbal_apicli_object_property(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, uint16_t prop, const bcmbal_apicli_prop_descr **descr);
+
+/* Get the number of subgroups present for a given group */
+static inline uint16_t bcmbal_apicli_get_subgroup_count(bcmbal_obj_id obj, bcmbal_mgt_group group)
+{
+ uint16_t count = 0;
+ uint32_t dummy;
+ while (bcmbal_apicli_object_struct_size(obj, group, count, &dummy, &dummy, &dummy, &dummy) != BCM_ERR_RANGE)
+ {
+ ++count;
+ }
+
+ return count;
+}
+
+/* Dump a single property */
+bcmos_errno bcmbal_apicli_dump_prop(bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data);
+
+/* Dump a single property value in C initializer format */
+bcmos_errno bcmbal_apicli_dump_prop_initializer(bcmcli_session *session, const bcmbal_apicli_prop_descr *pd, void *prop_data);
+
+/* Dump message */
+bcmos_errno bcmbal_apicli_msg_dump(bcmcli_session *session, bcmbal_obj *msg);
+
+/* Message group name */
+const char *bcmbal_apicli_mgt_group_to_str(bcmbal_mgt_group group);
+
+/* Convert an enum value to the corresponding string */
+#define BCMOLT_ENUM_STRING_VAL(enum_name, value) bcmcli_enum_stringval(enum_name ## _string_table, (value))
+
+/* Enum string tables */
+extern bcmcli_enum_val bcmbal_access_terminal_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_access_terminal_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_access_terminal_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_action_id_string_table[];
+extern bcmcli_enum_val bcmbal_action_cmd_id_string_table[];
+extern bcmcli_enum_val bcmbal_classifier_id_string_table[];
+extern bcmcli_enum_val bcmbal_pkt_tag_type_string_table[];
+extern bcmcli_enum_val bcmbal_control_string_table[];
+extern bcmcli_enum_val bcmbal_dest_type_string_table[];
+extern bcmcli_enum_val bcmbal_ds_miss_mode_string_table[];
+extern bcmcli_enum_val bcmbal_extra_bw_eligibility_type_string_table[];
+extern bcmcli_enum_val bcmbal_flow_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_flow_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_flow_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_flow_stat_id_string_table[];
+extern bcmcli_enum_val bcmbal_flow_type_string_table[];
+extern bcmcli_enum_val bcmbal_group_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_group_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_group_member_cmd_string_table[];
+extern bcmcli_enum_val bcmbal_group_owner_string_table[];
+extern bcmcli_enum_val bcmbal_interface_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_interface_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_interface_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_interface_stat_id_string_table[];
+extern bcmcli_enum_val bcmbal_intf_type_string_table[];
+extern bcmcli_enum_val bcmbal_iwf_mode_string_table[];
+extern bcmcli_enum_val bcmbal_packet_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_packet_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_packet_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_sla_id_string_table[];
+extern bcmcli_enum_val bcmbal_state_string_table[];
+extern bcmcli_enum_val bcmbal_status_string_table[];
+extern bcmcli_enum_val bcmbal_subscriber_terminal_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_subscriber_terminal_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_subscriber_terminal_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_subscriber_terminal_stat_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_bac_type_string_table[];
+extern bcmcli_enum_val bcmbal_tm_creation_mode_string_table[];
+extern bcmcli_enum_val bcmbal_tm_queue_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_queue_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_queue_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_queue_stat_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_cfg_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_child_type_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_dir_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_ind_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_key_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_owner_type_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_owner_agg_port_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_parent_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_sched_type_string_table[];
+extern bcmcli_enum_val bcmbal_tm_shaping_id_string_table[];
+extern bcmcli_enum_val bcmbal_tm_tcont_sla_id_string_table[];
+extern bcmcli_enum_val bcmbal_trx_type_string_table[];
+#endif /* BCMBAL_APICLI_HELPERS_H_ */
diff --git a/bal_release/src/lib/libbalapicli/bal_api_cli_types.h b/bal_release/src/lib/libbalapicli/bal_api_cli_types.h
new file mode 100644
index 0000000..8e38a6c
--- /dev/null
+++ b/bal_release/src/lib/libbalapicli/bal_api_cli_types.h
@@ -0,0 +1,60 @@
+/*
+<:copyright-BRCM:2016:DUAL/GPL:standard
+
+ Broadcom Proprietary and Confidential.(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 BCMBAL_APICLI_TYPES_H_
+#define BCMBAL_APICLI_TYPES_H_
+
+/* Property access */
+typedef enum
+{
+ BCMBAL_APICLI_PROP_ACCESS_ID_R = 0x1, /* Read access */
+ BCMBAL_APICLI_PROP_ACCESS_ID_W = 0x2, /* Write access */
+ BCMBAL_APICLI_PROP_ACCESS_ID_RW = 0x3, /* Read-write */
+} bcmbal_apicli_prop_access_id;
+
+/* Base data types */
+typedef enum
+{
+ BCMBAL_APICLI_BASE_TYPE_ID_SNUM, /* signed number */
+ BCMBAL_APICLI_BASE_TYPE_ID_UNUM, /* unsigned number */
+ BCMBAL_APICLI_BASE_TYPE_ID_UNUM_HEX, /* unsigned number printed in hex */
+ BCMBAL_APICLI_BASE_TYPE_ID_FLOAT, /* floating-point number */
+ BCMBAL_APICLI_BASE_TYPE_ID_BOOL, /* boolean (zero=no, nonzero=yes) */
+ BCMBAL_APICLI_BASE_TYPE_ID_STRING, /* string */
+ BCMBAL_APICLI_BASE_TYPE_ID_IPV4, /* IPv4 address */
+ BCMBAL_APICLI_BASE_TYPE_ID_MAC, /* MAC address */
+ BCMBAL_APICLI_BASE_TYPE_ID_ENUM, /* enum */
+ BCMBAL_APICLI_BASE_TYPE_ID_ENUM_MASK, /* bitmask enum */
+ BCMBAL_APICLI_BASE_TYPE_ID_STRUCT, /* struct */
+ BCMBAL_APICLI_BASE_TYPE_ID_UNION, /* union */
+ BCMBAL_APICLI_BASE_TYPE_ID_ARR_DYN, /* dynamically-sized array */
+ BCMBAL_APICLI_BASE_TYPE_ID_ARR_FIXED, /* fixed-size array */
+} bcmbal_apicli_base_type_id;
+
+#endif /* BCMBAL_APICLI_TYPES_H_ */
diff --git a/bal_release/src/lib/libcmdline/Makefile b/bal_release/src/lib/libcmdline/Makefile
new file mode 100644
index 0000000..5c5038d
--- /dev/null
+++ b/bal_release/src/lib/libcmdline/Makefile
@@ -0,0 +1,35 @@
+###############################################################################
+#
+# <: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 = cmdline
+MOD_TYPE = lib
+
+srcs = cmdline.c
+
diff --git a/bal_release/src/lib/libcmdline/cmdline.c b/bal_release/src/lib/libcmdline/cmdline.c
new file mode 100644
index 0000000..d20b10a
--- /dev/null
+++ b/bal_release/src/lib/libcmdline/cmdline.c
@@ -0,0 +1,135 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+/*
+ * cmdline.c - Command line argument helper
+ */
+
+#include <cmdline.h>
+
+/* Print usage information */
+bcmos_errno cl_print_usage(const char *app, const char *arg,
+ const cl_argument supported_args[], int num_supported_args,
+ cl_argument_usage_flags flags)
+{
+ const char *owner = "";
+ int i;
+
+ if (arg)
+ bcmos_printf("*** Error in parameter %s\n", arg);
+ if (app)
+ {
+ const char *p, *fname;
+ p = strrchr(app, '/');
+ fname = p ? p + 1 : app;
+ bcmos_printf("Usage: %s arguments\n", fname);
+ }
+ for (i = 0; i < num_supported_args; i++)
+ {
+ const cl_argument *opt = &supported_args[i];
+ if ((flags & CL_ARGUMENT_USAGE_FLAG_OWNER) != 0 &&
+ opt->owner && strcmp(opt->owner, owner))
+ {
+ owner = opt->owner;
+ bcmos_printf("\n%s options:\n", owner);
+ }
+ if (opt->short_name)
+ bcmos_printf("%-3s%c", opt->short_name, opt->long_name ? ',' : ' ');
+ else
+ bcmos_printf(" ");
+ bcmos_printf("%-20s %20s %s\n",
+ opt->long_name ? opt->long_name : "",
+ opt->extra_arg ? opt->extra_arg : "",
+ opt->description ? opt->description : "");
+ }
+ return BCM_ERR_PARM;
+}
+
+/* Get parameter by name */
+const cl_argument *cl_parm_get(const char *name, const cl_argument supported_args[], int num_supported_args)
+{
+ const cl_argument *opt = NULL;
+ int i;
+
+ /* Make sure that all mandatory parameters are set */
+ for (i = 0; i < num_supported_args; i++)
+ {
+ opt = &supported_args[i];
+ if ((opt->short_name && !strcmp(opt->short_name, name)) ||
+ (opt->long_name && !strcmp(opt->long_name, name)))
+ break;
+ }
+ return (i < num_supported_args) ? opt : NULL;
+}
+
+/* Validate command line parameters */
+bcmos_errno cl_validate(int argc, char *argv[],
+ const cl_argument supported_args[], int num_supported_args)
+{
+ bcmos_bool parm_set[num_supported_args];
+ bcmos_errno rc = BCM_ERR_OK;
+ int i;
+
+ memset(parm_set, 0, sizeof(parm_set));
+ for (i = 1; i < argc; i++)
+ {
+ const cl_argument *opt = cl_parm_get(argv[i], supported_args, num_supported_args);
+ if (opt == NULL)
+ {
+ bcmos_printf("*** Invalid parameter: %s\n", argv[i]);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ if (opt->extra_arg)
+ {
+ ++i;
+ if (i >= argc)
+ {
+ bcmos_printf("*** Argument is missing after %s\n", argv[i-1]);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+ parm_set[opt - supported_args] = BCMOS_TRUE;
+ }
+
+ /* Make sure that all mandatory parameters are set */
+ for (i = 0; i < num_supported_args; i++)
+ {
+ const cl_argument *opt = &supported_args[i];
+ if ((opt->flags & CL_ARGUMENT_FLAG_MANDATORY) && !parm_set[i])
+ {
+ bcmos_printf("*** Mandatory parameter %s is missing\n", opt->long_name ? opt->long_name : opt->short_name);
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+ return rc;
+}
diff --git a/bal_release/src/lib/libcmdline/cmdline.h b/bal_release/src/lib/libcmdline/cmdline.h
new file mode 100644
index 0000000..cad20b0
--- /dev/null
+++ b/bal_release/src/lib/libcmdline/cmdline.h
@@ -0,0 +1,101 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+/*
+ * cmdline.h - Command line argument helper
+ */
+
+#ifndef _CMDLINE_H_
+#define _CMDLINE_H_
+
+#include <bcmos_system.h>
+
+/** Argument flags */
+typedef enum
+{
+ CL_ARGUMENT_FLAG_NONE = 0,
+ CL_ARGUMENT_FLAG_MANDATORY = 0x1,
+} cl_argument_flags;
+
+/** Command line argument */
+typedef struct cl_argument
+{
+ const char *long_name; /**< Command line option: long form */
+ const char *short_name; /**< Command line option: short form */
+ const char *extra_arg; /**< Extra arguments */
+ const char *description; /**< Description */
+ const char *owner; /**< Owner module */
+ cl_argument_flags flags; /**< Command line argument flags */
+} cl_argument;
+
+/** Print usage flags */
+typedef enum
+{
+ CL_ARGUMENT_USAGE_FLAG_NONE = 0,
+ CL_ARGUMENT_USAGE_FLAG_OWNER = 0x1, /**< Print argument owners */
+} cl_argument_usage_flags;
+
+/** Print usage
+ * \param[in] app Application name. Can be NULL
+ * \param[in] arg Argument that triggered command line parsing error. Can be NULL
+ * \param[in] supported_args Array of supported arguments
+ * \param[in] num_supported_args Number of elements in supported_args[] array
+ * \param[in] flags Usage flags
+ * \returns BCM_ERR_PARM
+ */
+bcmos_errno cl_print_usage(const char *app, const char *arg,
+ const cl_argument supported_args[], int num_supported_args,
+ cl_argument_usage_flags flags);
+
+/** Validate parameters
+ *
+ * - make sure that there are no unknown parameters
+ * - make sure that all mandatory parameters are present
+ *
+ * \param[in] argc Number of command line arguments
+ * \param[in] argv Command line arguments
+ * \param[in] supported_args Array of supported arguments
+ * \param[in] num_supported_args Number of elements in supported_args[] array
+ * \returns BCM_ERR_OK or BCM_ERR_PARM
+ */
+bcmos_errno cl_validate(int argc, char *argv[],
+ const cl_argument supported_args[], int num_supported_args);
+
+/** Get CL parameter by name
+ *
+ * \param[in] name Parameter name
+ * \param[in] supported_args Supported arguments array
+ * \param[in] num_supported_args Supported arguments array size
+ * \returns argument descriptor pointer or NULL if not found
+ */
+const cl_argument *cl_parm_get(const char *name, const cl_argument supported_args[],
+ int num_supported_args);
+
+#endif /* _CMDLINE_H_ */
diff --git a/bal_release/src/lib/libobjmsg/Makefile b/bal_release/src/lib/libobjmsg/Makefile
new file mode 100644
index 0000000..15ff2d9
--- /dev/null
+++ b/bal_release/src/lib/libobjmsg/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 = balobjmsg
+MOD_TYPE = lib
+MOD_DEPS = common_include utils maple_sdk dev_log
+
+gen_bal_hdrs = bal_model_funcs.h bal_obj_msg_pack_unpack.h
+gen_bal_srcs = bal_model_funcs.c bal_obj_msg_pack_unpack.c
+srcs = bal_msg.c
diff --git a/bal_release/src/lib/libobjmsg/bal_model_funcs.c b/bal_release/src/lib/libobjmsg/bal_model_funcs.c
new file mode 100644
index 0000000..262999f
--- /dev/null
+++ b/bal_release/src/lib/libobjmsg/bal_model_funcs.c
@@ -0,0 +1,11384 @@
+#include <bcmos_system.h>
+#include "bal_model_funcs.h"
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_cfg_id_pack(bcmbal_access_terminal_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_cfg_id_unpack(bcmbal_access_terminal_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_ind_id_pack(bcmbal_access_terminal_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_ind_id_unpack(bcmbal_access_terminal_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_key_id_pack(bcmbal_access_terminal_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_key_id_unpack(bcmbal_access_terminal_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_id_pack(bcmbal_action_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_id_unpack(bcmbal_action_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_cmd_id_pack(bcmbal_action_cmd_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_cmd_id_unpack(bcmbal_action_cmd_id *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_classifier_id_pack(bcmbal_classifier_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_classifier_id_unpack(bcmbal_classifier_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_pkt_tag_type_pack(bcmbal_pkt_tag_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_pkt_tag_type_unpack(bcmbal_pkt_tag_type *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_control_pack(bcmbal_control this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_control_unpack(bcmbal_control *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_dest_type_pack(bcmbal_dest_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_dest_type_unpack(bcmbal_dest_type *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_ds_miss_mode_pack(bcmbal_ds_miss_mode this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_ds_miss_mode_unpack(bcmbal_ds_miss_mode *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_extra_bw_eligibility_type_pack(bcmbal_extra_bw_eligibility_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_extra_bw_eligibility_type_unpack(bcmbal_extra_bw_eligibility_type *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_cfg_id_pack(bcmbal_flow_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_cfg_id_unpack(bcmbal_flow_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_ind_id_pack(bcmbal_flow_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_ind_id_unpack(bcmbal_flow_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_key_id_pack(bcmbal_flow_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_key_id_unpack(bcmbal_flow_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_stat_id_pack(bcmbal_flow_stat_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_stat_id_unpack(bcmbal_flow_stat_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_type_pack(bcmbal_flow_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_type_unpack(bcmbal_flow_type *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_cfg_id_pack(bcmbal_group_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_cfg_id_unpack(bcmbal_group_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_key_id_pack(bcmbal_group_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_key_id_unpack(bcmbal_group_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_cmd_pack(bcmbal_group_member_cmd this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_cmd_unpack(bcmbal_group_member_cmd *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_owner_pack(bcmbal_group_owner this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_owner_unpack(bcmbal_group_owner *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_cfg_id_pack(bcmbal_interface_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_cfg_id_unpack(bcmbal_interface_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_ind_id_pack(bcmbal_interface_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_ind_id_unpack(bcmbal_interface_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_key_id_pack(bcmbal_interface_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_key_id_unpack(bcmbal_interface_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_stat_id_pack(bcmbal_interface_stat_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_stat_id_unpack(bcmbal_interface_stat_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_intf_type_pack(bcmbal_intf_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_intf_type_unpack(bcmbal_intf_type *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_iwf_mode_pack(bcmbal_iwf_mode this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_iwf_mode_unpack(bcmbal_iwf_mode *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_cfg_id_pack(bcmbal_packet_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_cfg_id_unpack(bcmbal_packet_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_ind_id_pack(bcmbal_packet_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_ind_id_unpack(bcmbal_packet_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_key_id_pack(bcmbal_packet_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_key_id_unpack(bcmbal_packet_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sla_id_pack(bcmbal_sla_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sla_id_unpack(bcmbal_sla_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_state_pack(bcmbal_state this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_state_unpack(bcmbal_state *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_status_pack(bcmbal_status this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_status_unpack(bcmbal_status *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_cfg_id_pack(bcmbal_subscriber_terminal_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_cfg_id_unpack(bcmbal_subscriber_terminal_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_ind_id_pack(bcmbal_subscriber_terminal_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_ind_id_unpack(bcmbal_subscriber_terminal_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_key_id_pack(bcmbal_subscriber_terminal_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_key_id_unpack(bcmbal_subscriber_terminal_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_stat_id_pack(bcmbal_subscriber_terminal_stat_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_stat_id_unpack(bcmbal_subscriber_terminal_stat_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_bac_type_pack(bcmbal_tm_bac_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_bac_type_unpack(bcmbal_tm_bac_type *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_creation_mode_pack(bcmbal_tm_creation_mode this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_creation_mode_unpack(bcmbal_tm_creation_mode *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_cfg_id_pack(bcmbal_tm_queue_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_cfg_id_unpack(bcmbal_tm_queue_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ind_id_pack(bcmbal_tm_queue_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ind_id_unpack(bcmbal_tm_queue_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_key_id_pack(bcmbal_tm_queue_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_key_id_unpack(bcmbal_tm_queue_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_stat_id_pack(bcmbal_tm_queue_stat_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_stat_id_unpack(bcmbal_tm_queue_stat_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_cfg_id_pack(bcmbal_tm_sched_cfg_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_cfg_id_unpack(bcmbal_tm_sched_cfg_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_child_type_pack(bcmbal_tm_sched_child_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_child_type_unpack(bcmbal_tm_sched_child_type *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_dir_pack(bcmbal_tm_sched_dir this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_dir_unpack(bcmbal_tm_sched_dir *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_ind_id_pack(bcmbal_tm_sched_ind_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_ind_id_unpack(bcmbal_tm_sched_ind_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_key_id_pack(bcmbal_tm_sched_key_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u16(buf, (uint16_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_key_id_unpack(bcmbal_tm_sched_key_id *this, bcmbal_buf *buf)
+{
+ uint16_t num_val;
+ if (!bcmbal_buf_read_u16(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_type_pack(bcmbal_tm_sched_owner_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_type_unpack(bcmbal_tm_sched_owner_type *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_agg_port_id_pack(bcmbal_tm_sched_owner_agg_port_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_agg_port_id_unpack(bcmbal_tm_sched_owner_agg_port_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_parent_id_pack(bcmbal_tm_sched_parent_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_parent_id_unpack(bcmbal_tm_sched_parent_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_type_pack(bcmbal_tm_sched_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u8(buf, (uint8_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_type_unpack(bcmbal_tm_sched_type *this, bcmbal_buf *buf)
+{
+ uint8_t num_val;
+ if (!bcmbal_buf_read_u8(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_shaping_id_pack(bcmbal_tm_shaping_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_shaping_id_unpack(bcmbal_tm_shaping_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_tcont_sla_id_pack(bcmbal_tm_tcont_sla_id this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u64(buf, (uint64_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_tcont_sla_id_unpack(bcmbal_tm_tcont_sla_id *this, bcmbal_buf *buf)
+{
+ uint64_t num_val;
+ if (!bcmbal_buf_read_u64(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_trx_type_pack(bcmbal_trx_type this, bcmbal_buf *buf)
+{
+ return bcmbal_buf_write_u32(buf, (uint32_t) this);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_trx_type_unpack(bcmbal_trx_type *this, bcmbal_buf *buf)
+{
+ uint32_t num_val;
+ if (!bcmbal_buf_read_u32(buf, &num_val))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *this = num_val;
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_action_set_default(bcmbal_action *this)
+{
+ this->presence_mask = (bcmbal_action_id) 0;
+ this->cmds_bitmask = (bcmbal_action_cmd_id) 0;
+ this->o_vid = 0;
+ this->o_pbits = 0;
+ this->o_tpid = 0;
+ this->i_vid = 0;
+ this->i_pbits = 0;
+ this->i_tpid = 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_pack(const bcmbal_action *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_action_id_pack(this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_action_cmd_id_pack(this->cmds_bitmask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->o_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->o_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->o_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->i_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0020) == 0x0020))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->i_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0040) == 0x0040))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->i_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_action_get_packed_length(const bcmbal_action *this)
+{
+ uint32_t count = 8;
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0020) == 0x0020))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0040) == 0x0040))
+ {
+ count += 2;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_unpack(bcmbal_action *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_action_id_unpack(&this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_action_cmd_id_unpack(&this->cmds_bitmask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->o_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->o_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->o_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->i_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0020) == 0x0020))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->i_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0040) == 0x0040))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->i_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_action_id presence_mask;
+ if (!bcmbal_action_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0020) == 0x0020))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0040) == 0x0040))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_action_bounds_check(const bcmbal_action *this)
+{
+ if ((this->presence_mask & 0xFFFFFFFFFFFFFF80ULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if ((this->cmds_bitmask & 0xFFFFE000UL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_aggregation_port_id_list_u8_set_default(bcmbal_aggregation_port_id_list_u8 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_aggregation_port_id_list_u8_pack(const bcmbal_aggregation_port_id_list_u8 *this, bcmbal_buf *buf)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_write_u8(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_aggregation_port_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_aggregation_port_id_list_u8_get_packed_length(const bcmbal_aggregation_port_id_list_u8 *this)
+{
+ return 1 + (2 * this->len);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_aggregation_port_id_list_u8_unpack(bcmbal_aggregation_port_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_read_u8(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_aggregation_port_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_aggregation_port_id *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_aggregation_port_id));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_aggregation_port_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint8_t len;
+ if (!bcmbal_buf_read_u8(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_aggregation_port_id) * len);
+ if (!bcmbal_buf_skip(packed, len * 2))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_aggregation_port_id_list_u8_bounds_check(const bcmbal_aggregation_port_id_list_u8 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_classifier_set_default(bcmbal_classifier *this)
+{
+ this->presence_mask = (bcmbal_classifier_id) 0;
+ this->o_tpid = 0;
+ this->o_vid = 0;
+ this->i_tpid = 0;
+ this->i_vid = 0;
+ this->o_pbits = 0;
+ this->i_pbits = 0;
+ this->ether_type = 0;
+ bcmos_mac_address_init(&this->dst_mac);
+ bcmos_mac_address_init(&this->src_mac);
+ this->ip_proto = 0;
+ bcmos_ipv4_address_init(&this->dst_ip);
+ bcmos_ipv4_address_init(&this->src_ip);
+ this->src_port = 0;
+ this->dst_port = 0;
+ this->pkt_tag_type = (bcmbal_pkt_tag_type) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_classifier_pack(const bcmbal_classifier *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_classifier_id_pack(this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->o_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->o_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->i_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->i_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->o_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0020) == 0x0020))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->i_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0040) == 0x0040))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->ether_type))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0080) == 0x0080))
+ {
+ if (!bcmbal_buf_write_mac_address(buf, this->dst_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0100) == 0x0100))
+ {
+ if (!bcmbal_buf_write_mac_address(buf, this->src_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0200) == 0x0200))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->ip_proto))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0400) == 0x0400))
+ {
+ if (!bcmbal_buf_write_ipv4_address(buf, this->dst_ip))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0800) == 0x0800))
+ {
+ if (!bcmbal_buf_write_ipv4_address(buf, this->src_ip))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x1000) == 0x1000))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->src_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x2000) == 0x2000))
+ {
+ if (!bcmbal_buf_write_u16(buf, this->dst_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x4000) == 0x4000))
+ {
+ if (!bcmbal_pkt_tag_type_pack(this->pkt_tag_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_classifier_get_packed_length(const bcmbal_classifier *this)
+{
+ uint32_t count = 8;
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0020) == 0x0020))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0040) == 0x0040))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0080) == 0x0080))
+ {
+ count += 6;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0100) == 0x0100))
+ {
+ count += 6;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0200) == 0x0200))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0400) == 0x0400))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0800) == 0x0800))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x1000) == 0x1000))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x2000) == 0x2000))
+ {
+ count += 2;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x4000) == 0x4000))
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_classifier_unpack(bcmbal_classifier *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_classifier_id_unpack(&this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->o_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->o_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->i_tpid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->i_vid))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->o_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0020) == 0x0020))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->i_pbits))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0040) == 0x0040))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->ether_type))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0080) == 0x0080))
+ {
+ if (!bcmbal_buf_read_mac_address(buf, &this->dst_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0100) == 0x0100))
+ {
+ if (!bcmbal_buf_read_mac_address(buf, &this->src_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0200) == 0x0200))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->ip_proto))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0400) == 0x0400))
+ {
+ if (!bcmbal_buf_read_ipv4_address(buf, &this->dst_ip))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0800) == 0x0800))
+ {
+ if (!bcmbal_buf_read_ipv4_address(buf, &this->src_ip))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x1000) == 0x1000))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->src_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x2000) == 0x2000))
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->dst_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x4000) == 0x4000))
+ {
+ if (!bcmbal_pkt_tag_type_unpack(&this->pkt_tag_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_classifier_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_classifier_id presence_mask;
+ if (!bcmbal_classifier_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0020) == 0x0020))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0040) == 0x0040))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0080) == 0x0080))
+ {
+ if (!bcmbal_buf_skip(packed, 6))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0100) == 0x0100))
+ {
+ if (!bcmbal_buf_skip(packed, 6))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0200) == 0x0200))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0400) == 0x0400))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0800) == 0x0800))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x1000) == 0x1000))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x2000) == 0x2000))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x4000) == 0x4000))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_classifier_bounds_check(const bcmbal_classifier *this)
+{
+ if ((this->presence_mask & 0xFFFFFFFFFFFF8000ULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x4000) == 0x4000))
+ {
+ if ((this->pkt_tag_type & 0xFFFFFFF8UL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_dest_set_default(bcmbal_dest *this)
+{
+ this->type = (bcmbal_dest_type) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_dest_pack(const bcmbal_dest *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_dest_type_pack(this->type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (this->type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.nni.int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.sub_term.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u16(buf, this->u.sub_term.sub_term_uni))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u16(buf, this->u.sub_term.int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ {
+ }
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_dest_get_packed_length(const bcmbal_dest *this)
+{
+ uint32_t count = 4;
+ switch (this->type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ {
+ count += 4;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ {
+ count += 8;
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ {
+ }
+ break;
+ default:
+ break;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_dest_unpack(bcmbal_dest *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_dest_type_unpack(&this->type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (this->type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.nni.int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.sub_term.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u16(buf, &this->u.sub_term.sub_term_uni))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u16(buf, &this->u.sub_term.int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ {
+ }
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_dest_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_dest_type type;
+ if (!bcmbal_dest_type_unpack(&type, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ {
+ }
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_dest_bounds_check(const bcmbal_dest *this)
+{
+ switch (this->type)
+ {
+ case BCMBAL_DEST_TYPE_NNI:
+ {
+ }
+ break;
+ case BCMBAL_DEST_TYPE_SUB_TERM:
+ {
+ }
+ break;
+ case BCMBAL_DEST_TYPE_HOST:
+ {
+ }
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_flow_id_list_u32_set_default(bcmbal_flow_id_list_u32 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_id_list_u32_pack(const bcmbal_flow_id_list_u32 *this, bcmbal_buf *buf)
+{
+ uint32_t i0;
+ if (!bcmbal_buf_write_u32(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_flow_id_list_u32\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_flow_id_list_u32_get_packed_length(const bcmbal_flow_id_list_u32 *this)
+{
+ return 4 + (4 * this->len);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_id_list_u32_unpack(bcmbal_flow_id_list_u32 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint32_t i0;
+ if (!bcmbal_buf_read_u32(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_flow_id_list_u32\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_flow_id *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_flow_id));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_id_list_u32_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint32_t len;
+ if (!bcmbal_buf_read_u32(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_flow_id) * len);
+ if (!bcmbal_buf_skip(packed, len * 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_id_list_u32_bounds_check(const bcmbal_flow_id_list_u32 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_queue_ref_set_default(bcmbal_tm_queue_ref *this)
+{
+ this->sched_id = (bcmbal_tm_sched_id) 0;
+ this->queue_id = (bcmbal_tm_queue_id) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ref_pack(const bcmbal_tm_queue_ref *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->sched_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->queue_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ref_unpack(bcmbal_tm_queue_ref *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->sched_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->queue_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ref_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ (void)extra_mem;
+ return bcmbal_buf_skip(packed, 5);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ref_bounds_check(const bcmbal_tm_queue_ref *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_group_member_info_set_default(bcmbal_group_member_info *this)
+{
+ this->intf_id = (bcmbal_intf_id) 0;
+ this->svc_port_id = (bcmbal_service_port_id) 0;
+ this->action.presence_mask = (bcmbal_action_id) 0;
+ this->action.cmds_bitmask = (bcmbal_action_cmd_id) 0;
+ this->action.o_vid = 0;
+ this->action.o_pbits = 0;
+ this->action.o_tpid = 0;
+ this->action.i_vid = 0;
+ this->action.i_pbits = 0;
+ this->action.i_tpid = 0;
+ this->queue.sched_id = (bcmbal_tm_sched_id) 0;
+ this->queue.queue_id = (bcmbal_tm_queue_id) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_pack(const bcmbal_group_member_info *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_action_pack(&this->action, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_queue_ref_pack(&this->queue, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_group_member_info_get_packed_length(const bcmbal_group_member_info *this)
+{
+ return 11 + bcmbal_action_get_packed_length(&this->action);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_unpack(bcmbal_group_member_info *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_action_unpack(&this->action, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_queue_ref_unpack(&this->queue, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_action_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 5))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_bounds_check(const bcmbal_group_member_info *this)
+{
+ if (!bcmbal_action_bounds_check(&this->action))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_queue_ref_bounds_check(&this->queue))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_group_member_info_list_u16_set_default(bcmbal_group_member_info_list_u16 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_list_u16_pack(const bcmbal_group_member_info_list_u16 *this, bcmbal_buf *buf)
+{
+ uint16_t i0;
+ if (!bcmbal_buf_write_u16(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_group_member_info_list_u16\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_group_member_info_pack(&this->val[i0], buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_group_member_info_list_u16_get_packed_length(const bcmbal_group_member_info_list_u16 *this)
+{
+ uint32_t count = 2;
+ uint32_t i0;
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"len\" of struct \"bcmbal_group_member_info_list_u16\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return 0;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ count += bcmbal_group_member_info_get_packed_length(&this->val[i0]);
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_list_u16_unpack(bcmbal_group_member_info_list_u16 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint16_t i0;
+ if (!bcmbal_buf_read_u16(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_group_member_info_list_u16\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_group_member_info *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_group_member_info));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_group_member_info_unpack(&this->val[i0], buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_list_u16_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint16_t len;
+ uint16_t i0;
+ if (!bcmbal_buf_read_u16(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_group_member_info) * len);
+ for (i0 = 0; i0 < len; i0++)
+ {
+ if (!bcmbal_group_member_info_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_member_info_list_u16_bounds_check(const bcmbal_group_member_info_list_u16 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_password_set_default(bcmbal_password *this)
+{
+ memset(this->arr, 0, sizeof(this->arr));
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_password_pack(const bcmbal_password *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write(buf, this->arr, 10))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_password_unpack(bcmbal_password *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read(buf, this->arr, 10))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_password_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ (void)extra_mem;
+ return bcmbal_buf_skip(packed, 10);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_password_bounds_check(const bcmbal_password *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_registration_id_set_default(bcmbal_registration_id *this)
+{
+ memset(this->arr, 0, sizeof(this->arr));
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_registration_id_pack(const bcmbal_registration_id *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write(buf, this->arr, 36))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_registration_id_unpack(bcmbal_registration_id *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read(buf, this->arr, 36))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_registration_id_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ (void)extra_mem;
+ return bcmbal_buf_skip(packed, 36);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_registration_id_bounds_check(const bcmbal_registration_id *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_serial_number_set_default(bcmbal_serial_number *this)
+{
+ memset(this->vendor_id, 0, sizeof(this->vendor_id));
+ memset(this->vendor_specific, 0, sizeof(this->vendor_specific));
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_serial_number_pack(const bcmbal_serial_number *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write(buf, this->vendor_id, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write(buf, this->vendor_specific, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_serial_number_unpack(bcmbal_serial_number *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read(buf, this->vendor_id, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read(buf, this->vendor_specific, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_serial_number_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ (void)extra_mem;
+ return bcmbal_buf_skip(packed, 8);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_serial_number_bounds_check(const bcmbal_serial_number *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_service_port_id_list_u8_set_default(bcmbal_service_port_id_list_u8 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_service_port_id_list_u8_pack(const bcmbal_service_port_id_list_u8 *this, bcmbal_buf *buf)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_write_u8(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_service_port_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_service_port_id_list_u8_get_packed_length(const bcmbal_service_port_id_list_u8 *this)
+{
+ return 1 + (2 * this->len);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_service_port_id_list_u8_unpack(bcmbal_service_port_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_read_u8(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_service_port_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_service_port_id *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_service_port_id));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_service_port_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint8_t len;
+ if (!bcmbal_buf_read_u8(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_service_port_id) * len);
+ if (!bcmbal_buf_skip(packed, len * 2))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_service_port_id_list_u8_bounds_check(const bcmbal_service_port_id_list_u8 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_sla_set_default(bcmbal_sla *this)
+{
+ this->presence_mask = (bcmbal_sla_id) 0;
+ this->min_rate = 0;
+ this->max_rate = 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sla_pack(const bcmbal_sla *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_sla_id_pack(this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_write_u32(buf, this->min_rate))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u32(buf, this->max_rate))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_sla_get_packed_length(const bcmbal_sla *this)
+{
+ uint32_t count = 8;
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sla_unpack(bcmbal_sla *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_sla_id_unpack(&this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->min_rate))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->max_rate))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sla_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_sla_id presence_mask;
+ if (!bcmbal_sla_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sla_bounds_check(const bcmbal_sla *this)
+{
+ if ((this->presence_mask & 0xFFFFFFFFFFFFFFFCULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_sub_id_list_u16_set_default(bcmbal_sub_id_list_u16 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sub_id_list_u16_pack(const bcmbal_sub_id_list_u16 *this, bcmbal_buf *buf)
+{
+ uint16_t i0;
+ if (!bcmbal_buf_write_u16(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_sub_id_list_u16\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_sub_id_list_u16_get_packed_length(const bcmbal_sub_id_list_u16 *this)
+{
+ return 2 + (4 * this->len);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sub_id_list_u16_unpack(bcmbal_sub_id_list_u16 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint16_t i0;
+ if (!bcmbal_buf_read_u16(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_sub_id_list_u16\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_sub_id *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_sub_id));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sub_id_list_u16_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint16_t len;
+ if (!bcmbal_buf_read_u16(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_sub_id) * len);
+ if (!bcmbal_buf_skip(packed, len * 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_sub_id_list_u16_bounds_check(const bcmbal_sub_id_list_u16 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_red_set_default(bcmbal_tm_red *this)
+{
+ this->min_threshold = (bcmbal_percent) 0;
+ this->max_threshold = (bcmbal_percent) 0;
+ this->max_probability = (bcmbal_percent) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_red_pack(const bcmbal_tm_red *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->min_threshold))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->max_threshold))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->max_probability))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_red_unpack(bcmbal_tm_red *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->min_threshold))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->max_threshold))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->max_probability))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_red_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ (void)extra_mem;
+ return bcmbal_buf_skip(packed, 3);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_red_bounds_check(const bcmbal_tm_red *this)
+{
+ if (this->min_threshold > (bcmbal_percent) 100)
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (this->max_threshold > (bcmbal_percent) 100)
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (this->max_probability > (bcmbal_percent) 100)
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_bac_set_default(bcmbal_tm_bac *this)
+{
+ this->type = (bcmbal_tm_bac_type) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_bac_pack(const bcmbal_tm_bac *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_tm_bac_type_pack(this->type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (this->type)
+ {
+ case BCMBAL_TM_BAC_TYPE_TAILDROP:
+ {
+ if (!bcmbal_buf_write_u32(buf, this->u.taildrop.max_size))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_RED:
+ {
+ if (!bcmbal_tm_red_pack(&this->u.red.red, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WRED:
+ {
+ if (!bcmbal_tm_red_pack(&this->u.wred.green, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_red_pack(&this->u.wred.yellow, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_red_pack(&this->u.wred.red, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WTAILDROP:
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_bac_get_packed_length(const bcmbal_tm_bac *this)
+{
+ uint32_t count = 1;
+ switch (this->type)
+ {
+ case BCMBAL_TM_BAC_TYPE_TAILDROP:
+ {
+ count += 4;
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_RED:
+ {
+ count += 3;
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WRED:
+ {
+ count += 9;
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WTAILDROP:
+ default:
+ break;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_bac_unpack(bcmbal_tm_bac *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_tm_bac_type_unpack(&this->type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (this->type)
+ {
+ case BCMBAL_TM_BAC_TYPE_TAILDROP:
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->u.taildrop.max_size))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_RED:
+ {
+ if (!bcmbal_tm_red_unpack(&this->u.red.red, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WRED:
+ {
+ if (!bcmbal_tm_red_unpack(&this->u.wred.green, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_red_unpack(&this->u.wred.yellow, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_red_unpack(&this->u.wred.red, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WTAILDROP:
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_bac_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_tm_bac_type type;
+ if (!bcmbal_tm_bac_type_unpack(&type, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (type)
+ {
+ case BCMBAL_TM_BAC_TYPE_TAILDROP:
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_RED:
+ {
+ if (!bcmbal_buf_skip(packed, 3))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WRED:
+ {
+ if (!bcmbal_buf_skip(packed, 3))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 3))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 3))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WTAILDROP:
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_bac_bounds_check(const bcmbal_tm_bac *this)
+{
+ switch (this->type)
+ {
+ case BCMBAL_TM_BAC_TYPE_TAILDROP:
+ {
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_RED:
+ {
+ if (!bcmbal_tm_red_bounds_check(&this->u.red.red))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WRED:
+ {
+ if (!bcmbal_tm_red_bounds_check(&this->u.wred.green))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_red_bounds_check(&this->u.wred.yellow))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_tm_red_bounds_check(&this->u.wred.red))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_BAC_TYPE_WTAILDROP:
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_queue_id_list_u8_set_default(bcmbal_tm_queue_id_list_u8 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_id_list_u8_pack(const bcmbal_tm_queue_id_list_u8 *this, bcmbal_buf *buf)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_write_u8(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_tm_queue_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_queue_id_list_u8_get_packed_length(const bcmbal_tm_queue_id_list_u8 *this)
+{
+ return 1 + this->len;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_id_list_u8_unpack(bcmbal_tm_queue_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_read_u8(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_tm_queue_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_tm_queue_id *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_tm_queue_id));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint8_t len;
+ if (!bcmbal_buf_read_u8(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_tm_queue_id) * len);
+ if (!bcmbal_buf_skip(packed, len * 1))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_id_list_u8_bounds_check(const bcmbal_tm_queue_id_list_u8 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_sched_id_list_u8_set_default(bcmbal_tm_sched_id_list_u8 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_id_list_u8_pack(const bcmbal_tm_sched_id_list_u8 *this, bcmbal_buf *buf)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_write_u8(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_tm_sched_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_sched_id_list_u8_get_packed_length(const bcmbal_tm_sched_id_list_u8 *this)
+{
+ return 1 + (4 * this->len);
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_id_list_u8_unpack(bcmbal_tm_sched_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ uint8_t i0;
+ if (!bcmbal_buf_read_u8(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_tm_sched_id_list_u8\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (bcmbal_tm_sched_id *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(bcmbal_tm_sched_id));
+ }
+ }
+
+ for (i0 = 0; i0 < this->len; i0++)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->val[i0]))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint8_t len;
+ if (!bcmbal_buf_read_u8(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(bcmbal_tm_sched_id) * len);
+ if (!bcmbal_buf_skip(packed, len * 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_id_list_u8_bounds_check(const bcmbal_tm_sched_id_list_u8 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_sched_owner_set_default(bcmbal_tm_sched_owner *this)
+{
+ this->type = (bcmbal_tm_sched_owner_type) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_pack(const bcmbal_tm_sched_owner *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_tm_sched_owner_type_pack(this->type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (this->type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ if (!bcmbal_intf_type_pack(this->u.interface.intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.interface.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.sub_term.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.sub_term.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ if (!bcmbal_tm_sched_owner_agg_port_id_pack(this->u.agg_port.presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->u.agg_port.presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->u.agg_port.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->u.agg_port.presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.agg_port.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->u.agg_port.presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->u.agg_port.agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ if (!bcmbal_buf_write_u8(buf, this->u.uni.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->u.uni.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write_u8(buf, this->u.uni.idx))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ {
+ if (!bcmbal_buf_write_u32(buf, this->u.virtual.idx))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED:
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_sched_owner_get_packed_length(const bcmbal_tm_sched_owner *this)
+{
+ uint32_t count = 1;
+ switch (this->type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ count += 8;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ {
+ count += 8;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ count += 15;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ count += 6;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ {
+ count += 4;
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED:
+ default:
+ break;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_unpack(bcmbal_tm_sched_owner *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_tm_sched_owner_type_unpack(&this->type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (this->type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ if (!bcmbal_intf_type_unpack(&this->u.interface.intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.interface.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.sub_term.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.sub_term.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ if (!bcmbal_tm_sched_owner_agg_port_id_unpack(&this->u.agg_port.presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->u.agg_port.presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->u.agg_port.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->u.agg_port.presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.agg_port.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->u.agg_port.presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->u.agg_port.agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->u.uni.intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->u.uni.sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_read_u8(buf, &this->u.uni.idx))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->u.virtual.idx))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED:
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_tm_sched_owner_type type;
+ if (!bcmbal_tm_sched_owner_type_unpack(&type, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ switch (type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ bcmbal_tm_sched_owner_agg_port_id presence_mask;
+ if (!bcmbal_tm_sched_owner_agg_port_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED:
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_owner_bounds_check(const bcmbal_tm_sched_owner *this)
+{
+ switch (this->type)
+ {
+ case BCMBAL_TM_SCHED_OWNER_TYPE_INTERFACE:
+ {
+ switch (this->u.interface.intf_type)
+ {
+ case BCMBAL_INTF_TYPE_NNI:
+ break;
+ case BCMBAL_INTF_TYPE_PON:
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_SUB_TERM:
+ {
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT:
+ {
+ if ((this->u.agg_port.presence_mask & 0xFFFFFFFFFFFFFFF8ULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNI:
+ {
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_VIRTUAL:
+ {
+ }
+ break;
+ case BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED:
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_sched_parent_set_default(bcmbal_tm_sched_parent *this)
+{
+ this->presence_mask = (bcmbal_tm_sched_parent_id) 0;
+ this->sched_id = (bcmbal_tm_sched_id) 0;
+ this->priority = (bcmbal_tm_priority) 0;
+ this->weight = (bcmbal_tm_weight) 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_parent_pack(const bcmbal_tm_sched_parent *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_tm_sched_parent_id_pack(this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->sched_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->weight))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_sched_parent_get_packed_length(const bcmbal_tm_sched_parent *this)
+{
+ uint32_t count = 8;
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ count += 1;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_parent_unpack(bcmbal_tm_sched_parent *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_tm_sched_parent_id_unpack(&this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->sched_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->weight))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_parent_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_tm_sched_parent_id presence_mask;
+ if (!bcmbal_tm_sched_parent_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_parent_bounds_check(const bcmbal_tm_sched_parent *this)
+{
+ if ((this->presence_mask & 0xFFFFFFFFFFFFFFF8ULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_shaping_set_default(bcmbal_tm_shaping *this)
+{
+ this->presence_mask = (bcmbal_tm_shaping_id) 0;
+ this->sbr = 0;
+ this->pbr = 0;
+ this->burst = 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_shaping_pack(const bcmbal_tm_shaping *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_tm_shaping_id_pack(this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_write_u32(buf, this->sbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u32(buf, this->pbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_write_u32(buf, this->burst))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_shaping_get_packed_length(const bcmbal_tm_shaping *this)
+{
+ uint32_t count = 8;
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ count += 4;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_shaping_unpack(bcmbal_tm_shaping *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_tm_shaping_id_unpack(&this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->sbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->pbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->burst))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_shaping_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_tm_shaping_id presence_mask;
+ if (!bcmbal_tm_shaping_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_shaping_bounds_check(const bcmbal_tm_shaping *this)
+{
+ if ((this->presence_mask & 0xFFFFFFFFFFFFFFF8ULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_tcont_sla_set_default(bcmbal_tm_tcont_sla *this)
+{
+ this->presence_mask = (bcmbal_tm_tcont_sla_id) 0;
+ this->extra_bw_elig = BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NONE;
+ this->nrt_cbr = 0;
+ this->rt_cbr = 0;
+ this->rt_profile = 0;
+ this->nrt_profile = 0;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_tcont_sla_pack(const bcmbal_tm_tcont_sla *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_tm_tcont_sla_id_pack(this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_extra_bw_eligibility_type_pack(this->extra_bw_elig, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->nrt_cbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->rt_cbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->rt_profile))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_write_u8(buf, this->nrt_profile))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_tcont_sla_get_packed_length(const bcmbal_tm_tcont_sla *this)
+{
+ uint32_t count = 8;
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ count += 1;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ count += 1;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_tcont_sla_unpack(bcmbal_tm_tcont_sla *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_tm_tcont_sla_id_unpack(&this->presence_mask, buf))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_extra_bw_eligibility_type_unpack(&this->extra_bw_elig, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->nrt_cbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->rt_cbr))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->rt_profile))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->nrt_profile))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_tcont_sla_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ bcmbal_tm_tcont_sla_id presence_mask;
+ if (!bcmbal_tm_tcont_sla_id_unpack(&presence_mask, packed))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) presence_mask & 0x0001) == 0x0001))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0002) == 0x0002))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0004) == 0x0004))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0008) == 0x0008))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((((uint64_t) presence_mask & 0x0010) == 0x0010))
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_tcont_sla_bounds_check(const bcmbal_tm_tcont_sla *this)
+{
+ if ((this->presence_mask & 0xFFFFFFFFFFFFFFE0ULL) != 0)
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((((uint64_t) this->presence_mask & 0x0001) == 0x0001))
+ {
+ switch (this->extra_bw_elig)
+ {
+ case BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NONE:
+ break;
+ case BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NOT_ASSURED:
+ break;
+ case BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_BEST_EFFORT:
+ break;
+ default:
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_u8_list_u32_set_default(bcmbal_u8_list_u32 *this)
+{
+ this->len = 0;
+ this->val = NULL;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_u8_list_u32_pack(const bcmbal_u8_list_u32 *this, bcmbal_buf *buf)
+{
+ if (!bcmbal_buf_write_u32(buf, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_u8_list_u32\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+
+ if (!bcmbal_buf_write(buf, this->val, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_u8_list_u32_get_packed_length(const bcmbal_u8_list_u32 *this)
+{
+ return 4 + this->len;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_u8_list_u32_unpack(bcmbal_u8_list_u32 *this, bcmbal_buf *buf, void **extra_mem)
+{
+ if (!bcmbal_buf_read_u32(buf, &this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ if ((this->len > 0) && (this->val == NULL))
+ {
+ if (extra_mem == NULL)
+ {
+ bcmos_trace(BCMOS_TRACE_LEVEL_ERROR, "Error: list field \"val\" of struct \"bcmbal_u8_list_u32\" is uninitialized (NULL). You must allocate memory for this pointer before sending/receiving the message.\n");
+ return BCMOS_FALSE;
+ }
+ else
+ {
+ this->val = (uint8_t *) *extra_mem;
+ *extra_mem = ((uint8_t *) *extra_mem) + BCMOS_ROUND_TO_WORD(this->len * sizeof(uint8_t));
+ }
+ }
+
+ if (!bcmbal_buf_read(buf, this->val, this->len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_u8_list_u32_scan(bcmbal_buf *packed, uint32_t *extra_mem)
+{
+ uint32_t len;
+ if (!bcmbal_buf_read_u32(packed, &len))
+ {
+ return BCMOS_FALSE;
+ }
+
+ *extra_mem += BCMOS_ROUND_TO_WORD(sizeof(uint8_t) * len);
+ if (!bcmbal_buf_skip(packed, len * 1))
+ {
+ return BCMOS_FALSE;
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_u8_list_u32_bounds_check(const bcmbal_u8_list_u32 *this)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_access_terminal_key_set_default(bcmbal_access_terminal_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID)) != 0)
+ {
+ this->access_term_id = (bcmbal_access_id) 1;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_key_pack(const bcmbal_access_terminal_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->access_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_access_terminal_key_get_packed_length(const bcmbal_access_terminal_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_key_unpack(bcmbal_access_terminal_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->access_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_key_bounds_check(const bcmbal_access_terminal_key *this, bcmbal_presence_mask fields_present, bcmbal_access_terminal_key_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID)) != 0)
+ {
+ if (this->access_term_id < (bcmbal_access_id) 1)
+ {
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID;
+ return BCMOS_FALSE;
+ }
+
+ if (this->access_term_id > (bcmbal_access_id) 1)
+ {
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_KEY_ID_ACCESS_TERM_ID;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_access_terminal_cfg_data_set_default(bcmbal_access_terminal_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE)) != 0)
+ {
+ this->iwf_mode = BCMBAL_IWF_MODE_DIRECT_MAPPING;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_cfg_data_pack(const bcmbal_access_terminal_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE)) != 0)
+ {
+ if (!bcmbal_iwf_mode_pack(this->iwf_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_access_terminal_cfg_data_get_packed_length(const bcmbal_access_terminal_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_cfg_data_unpack(bcmbal_access_terminal_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE)) != 0)
+ {
+ if (!bcmbal_iwf_mode_unpack(&this->iwf_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_cfg_data_bounds_check(const bcmbal_access_terminal_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_access_terminal_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_CFG_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE)) != 0)
+ {
+ switch (this->iwf_mode)
+ {
+ case BCMBAL_IWF_MODE_DIRECT_MAPPING:
+ break;
+ case BCMBAL_IWF_MODE_PER_FLOW:
+ break;
+ default:
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_access_terminal_ind_data_set_default(bcmbal_access_terminal_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE)) != 0)
+ {
+ this->iwf_mode = BCMBAL_IWF_MODE_DIRECT_MAPPING;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_ind_data_pack(const bcmbal_access_terminal_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE)) != 0)
+ {
+ if (!bcmbal_iwf_mode_pack(this->iwf_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_access_terminal_ind_data_get_packed_length(const bcmbal_access_terminal_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_ind_data_unpack(bcmbal_access_terminal_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE)) != 0)
+ {
+ if (!bcmbal_iwf_mode_unpack(&this->iwf_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_access_terminal_ind_data_bounds_check(const bcmbal_access_terminal_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_access_terminal_ind_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_IND_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_IND_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE)) != 0)
+ {
+ switch (this->iwf_mode)
+ {
+ case BCMBAL_IWF_MODE_DIRECT_MAPPING:
+ break;
+ case BCMBAL_IWF_MODE_PER_FLOW:
+ break;
+ default:
+ *failed_prop = BCMBAL_ACCESS_TERMINAL_IND_ID_IWF_MODE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_flow_key_set_default(bcmbal_flow_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_ID)) != 0)
+ {
+ this->flow_id = (bcmbal_flow_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_TYPE)) != 0)
+ {
+ this->flow_type = (bcmbal_flow_type) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_key_pack(const bcmbal_flow_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->flow_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_flow_type_pack(this->flow_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_flow_key_get_packed_length(const bcmbal_flow_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_key_unpack(bcmbal_flow_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->flow_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_flow_type_unpack(&this->flow_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_key_bounds_check(const bcmbal_flow_key *this, bcmbal_presence_mask fields_present, bcmbal_flow_key_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_KEY_ID_FLOW_TYPE)) != 0)
+ {
+ switch (this->flow_type)
+ {
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ break;
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ break;
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ break;
+ case BCMBAL_FLOW_TYPE_MULTICAST:
+ break;
+ default:
+ *failed_prop = BCMBAL_FLOW_KEY_ID_FLOW_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_flow_cfg_data_set_default(bcmbal_flow_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID)) != 0)
+ {
+ this->access_int_id = (bcmbal_intf_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID)) != 0)
+ {
+ this->network_int_id = (bcmbal_intf_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_ID)) != 0)
+ {
+ this->sub_term_id = (bcmbal_sub_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX)) != 0)
+ {
+ this->sub_term_uni_idx = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ this->svc_port_id = (bcmbal_service_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_AGG_PORT_ID)) != 0)
+ {
+ this->agg_port_id = (bcmbal_aggregation_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_RESOLVE_MAC)) != 0)
+ {
+ this->resolve_mac = BCMOS_FALSE;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_CLASSIFIER)) != 0)
+ {
+ this->classifier.presence_mask = (bcmbal_classifier_id) 0;
+ this->classifier.o_tpid = 0;
+ this->classifier.o_vid = 0;
+ this->classifier.i_tpid = 0;
+ this->classifier.i_vid = 0;
+ this->classifier.o_pbits = 0;
+ this->classifier.i_pbits = 0;
+ this->classifier.ether_type = 0;
+ bcmos_mac_address_init(&this->classifier.dst_mac);
+ bcmos_mac_address_init(&this->classifier.src_mac);
+ this->classifier.ip_proto = 0;
+ bcmos_ipv4_address_init(&this->classifier.dst_ip);
+ bcmos_ipv4_address_init(&this->classifier.src_ip);
+ this->classifier.src_port = 0;
+ this->classifier.dst_port = 0;
+ this->classifier.pkt_tag_type = (bcmbal_pkt_tag_type) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACTION)) != 0)
+ {
+ this->action.presence_mask = (bcmbal_action_id) 0;
+ this->action.cmds_bitmask = (bcmbal_action_cmd_id) 0;
+ this->action.o_vid = 0;
+ this->action.o_pbits = 0;
+ this->action.o_tpid = 0;
+ this->action.i_vid = 0;
+ this->action.i_pbits = 0;
+ this->action.i_tpid = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SLA)) != 0)
+ {
+ this->sla.presence_mask = (bcmbal_sla_id) 0;
+ this->sla.min_rate = 0;
+ this->sla.max_rate = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_COOKIE)) != 0)
+ {
+ this->cookie = (bcmbal_cookie) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_PRIORITY)) != 0)
+ {
+ this->priority = 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_GROUP_ID)) != 0)
+ {
+ this->group_id = (bcmbal_group_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_QUEUE)) != 0)
+ {
+ this->queue.sched_id = (bcmbal_tm_sched_id) 0;
+ this->queue.queue_id = (bcmbal_tm_queue_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_cfg_data_pack(const bcmbal_flow_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->access_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->network_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX)) != 0)
+ {
+ if (!bcmbal_buf_write_u8(buf, this->sub_term_uni_idx))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_RESOLVE_MAC)) != 0)
+ {
+ if (!bcmbal_buf_write_bool(buf, this->resolve_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_pack(&this->classifier, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_pack(&this->action, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_pack(&this->sla, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, (uint64_t) this->cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_GROUP_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->group_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_QUEUE)) != 0)
+ {
+ if (!bcmbal_tm_queue_ref_pack(&this->queue, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_flow_cfg_data_get_packed_length(const bcmbal_flow_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_AGG_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_RESOLVE_MAC)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_CLASSIFIER)) != 0)
+ {
+ count += bcmbal_classifier_get_packed_length(&this->classifier);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACTION)) != 0)
+ {
+ count += bcmbal_action_get_packed_length(&this->action);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SLA)) != 0)
+ {
+ count += bcmbal_sla_get_packed_length(&this->sla);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_COOKIE)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_PRIORITY)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_GROUP_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_QUEUE)) != 0)
+ {
+ count += 5;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_cfg_data_unpack(bcmbal_flow_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->access_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->network_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX)) != 0)
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->sub_term_uni_idx))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_RESOLVE_MAC)) != 0)
+ {
+ if (!bcmbal_buf_read_bool(buf, &this->resolve_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_unpack(&this->classifier, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_unpack(&this->action, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_unpack(&this->sla, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, (uint64_t *) &this->cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_GROUP_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->group_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_QUEUE)) != 0)
+ {
+ if (!bcmbal_tm_queue_ref_unpack(&this->queue, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACCESS_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_NETWORK_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SUB_TERM_UNI_IDX)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_RESOLVE_MAC)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_GROUP_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_QUEUE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 5))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_cfg_data_bounds_check(const bcmbal_flow_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_flow_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_FLOW_CFG_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_FLOW_CFG_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_bounds_check(&this->classifier))
+ {
+ *failed_prop = BCMBAL_FLOW_CFG_ID_CLASSIFIER;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_bounds_check(&this->action))
+ {
+ *failed_prop = BCMBAL_FLOW_CFG_ID_ACTION;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_bounds_check(&this->sla))
+ {
+ *failed_prop = BCMBAL_FLOW_CFG_ID_SLA;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_PRIORITY)) != 0)
+ {
+ if (this->priority < 1)
+ {
+ *failed_prop = BCMBAL_FLOW_CFG_ID_PRIORITY;
+ return BCMOS_FALSE;
+ }
+
+ if (this->priority > 255)
+ {
+ *failed_prop = BCMBAL_FLOW_CFG_ID_PRIORITY;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_CFG_ID_QUEUE)) != 0)
+ {
+ if (!bcmbal_tm_queue_ref_bounds_check(&this->queue))
+ {
+ *failed_prop = BCMBAL_FLOW_CFG_ID_QUEUE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_flow_stat_data_set_default(bcmbal_flow_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_PACKETS)) != 0)
+ {
+ this->rx_packets = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_BYTES)) != 0)
+ {
+ this->rx_bytes = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_PACKETS)) != 0)
+ {
+ this->tx_packets = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_BYTES)) != 0)
+ {
+ this->tx_bytes = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_stat_data_pack(const bcmbal_flow_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->rx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->rx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->tx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->tx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_flow_stat_data_get_packed_length(const bcmbal_flow_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_PACKETS)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_BYTES)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_PACKETS)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_BYTES)) != 0)
+ {
+ count += 8;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_stat_data_unpack(bcmbal_flow_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->rx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->rx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->tx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->tx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_stat_data_bounds_check(const bcmbal_flow_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_flow_stat_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_flow_ind_data_set_default(bcmbal_flow_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACCESS_INT_ID)) != 0)
+ {
+ this->access_int_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_NETWORK_INT_ID)) != 0)
+ {
+ this->network_int_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SUB_TERM_ID)) != 0)
+ {
+ this->sub_term_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ this->svc_port_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_AGG_PORT_ID)) != 0)
+ {
+ this->agg_port_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_RESOLVE_MAC)) != 0)
+ {
+ this->resolve_mac = BCMOS_FALSE;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_BASE_TC_ID)) != 0)
+ {
+ this->base_tc_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_CLASSIFIER)) != 0)
+ {
+ this->classifier.presence_mask = (bcmbal_classifier_id) 0;
+ this->classifier.o_tpid = 0;
+ this->classifier.o_vid = 0;
+ this->classifier.i_tpid = 0;
+ this->classifier.i_vid = 0;
+ this->classifier.o_pbits = 0;
+ this->classifier.i_pbits = 0;
+ this->classifier.ether_type = 0;
+ bcmos_mac_address_init(&this->classifier.dst_mac);
+ bcmos_mac_address_init(&this->classifier.src_mac);
+ this->classifier.ip_proto = 0;
+ bcmos_ipv4_address_init(&this->classifier.dst_ip);
+ bcmos_ipv4_address_init(&this->classifier.src_ip);
+ this->classifier.src_port = 0;
+ this->classifier.dst_port = 0;
+ this->classifier.pkt_tag_type = (bcmbal_pkt_tag_type) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACTION)) != 0)
+ {
+ this->action.presence_mask = (bcmbal_action_id) 0;
+ this->action.cmds_bitmask = (bcmbal_action_cmd_id) 0;
+ this->action.o_vid = 0;
+ this->action.o_pbits = 0;
+ this->action.o_tpid = 0;
+ this->action.i_vid = 0;
+ this->action.i_pbits = 0;
+ this->action.i_tpid = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SLA)) != 0)
+ {
+ this->sla.presence_mask = (bcmbal_sla_id) 0;
+ this->sla.min_rate = 0;
+ this->sla.max_rate = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_COOKIE)) != 0)
+ {
+ this->cookie = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_PRIORITY)) != 0)
+ {
+ this->priority = 1;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_ind_data_pack(const bcmbal_flow_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACCESS_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->access_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_NETWORK_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->network_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, this->sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_RESOLVE_MAC)) != 0)
+ {
+ if (!bcmbal_buf_write_bool(buf, this->resolve_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_BASE_TC_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->base_tc_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_pack(&this->classifier, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_pack(&this->action, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_pack(&this->sla, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, this->cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_flow_ind_data_get_packed_length(const bcmbal_flow_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACCESS_INT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_NETWORK_INT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SUB_TERM_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_AGG_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_RESOLVE_MAC)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_BASE_TC_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_CLASSIFIER)) != 0)
+ {
+ count += bcmbal_classifier_get_packed_length(&this->classifier);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACTION)) != 0)
+ {
+ count += bcmbal_action_get_packed_length(&this->action);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SLA)) != 0)
+ {
+ count += bcmbal_sla_get_packed_length(&this->sla);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_COOKIE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_PRIORITY)) != 0)
+ {
+ count += 2;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_ind_data_unpack(bcmbal_flow_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACCESS_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->access_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_NETWORK_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->network_int_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_RESOLVE_MAC)) != 0)
+ {
+ if (!bcmbal_buf_read_bool(buf, &this->resolve_mac))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_BASE_TC_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->base_tc_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_unpack(&this->classifier, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_unpack(&this->action, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_unpack(&this->sla, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACCESS_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_NETWORK_INT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_RESOLVE_MAC)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_BASE_TC_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_flow_ind_data_bounds_check(const bcmbal_flow_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_flow_ind_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_FLOW_IND_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_FLOW_IND_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_CLASSIFIER)) != 0)
+ {
+ if (!bcmbal_classifier_bounds_check(&this->classifier))
+ {
+ *failed_prop = BCMBAL_FLOW_IND_ID_CLASSIFIER;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_ACTION)) != 0)
+ {
+ if (!bcmbal_action_bounds_check(&this->action))
+ {
+ *failed_prop = BCMBAL_FLOW_IND_ID_ACTION;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_SLA)) != 0)
+ {
+ if (!bcmbal_sla_bounds_check(&this->sla))
+ {
+ *failed_prop = BCMBAL_FLOW_IND_ID_SLA;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_FLOW_IND_ID_PRIORITY)) != 0)
+ {
+ if (this->priority < 1)
+ {
+ *failed_prop = BCMBAL_FLOW_IND_ID_PRIORITY;
+ return BCMOS_FALSE;
+ }
+
+ if (this->priority > 255)
+ {
+ *failed_prop = BCMBAL_FLOW_IND_ID_PRIORITY;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_group_key_set_default(bcmbal_group_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_KEY_ID_GROUP_ID)) != 0)
+ {
+ this->group_id = (bcmbal_group_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_key_pack(const bcmbal_group_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_KEY_ID_GROUP_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->group_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_group_key_get_packed_length(const bcmbal_group_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_GROUP_KEY_ID_GROUP_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_key_unpack(bcmbal_group_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_KEY_ID_GROUP_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->group_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_KEY_ID_GROUP_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_key_bounds_check(const bcmbal_group_key *this, bcmbal_presence_mask fields_present, bcmbal_group_key_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_group_cfg_data_set_default(bcmbal_group_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS_CMD)) != 0)
+ {
+ this->members_cmd = (bcmbal_group_member_cmd) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS)) != 0)
+ {
+ this->members.len = 0;
+ this->members.val = NULL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_COOKIE)) != 0)
+ {
+ this->cookie = (bcmbal_cookie) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS)) != 0)
+ {
+ this->flows.len = 0;
+ this->flows.val = NULL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_OWNER)) != 0)
+ {
+ this->owner = BCMBAL_GROUP_OWNER_NONE;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_cfg_data_pack(const bcmbal_group_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS_CMD)) != 0)
+ {
+ if (!bcmbal_group_member_cmd_pack(this->members_cmd, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS)) != 0)
+ {
+ if (!bcmbal_group_member_info_list_u16_pack(&this->members, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, (uint64_t) this->cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS)) != 0)
+ {
+ if (!bcmbal_flow_id_list_u32_pack(&this->flows, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_group_owner_pack(this->owner, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_group_cfg_data_get_packed_length(const bcmbal_group_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS_CMD)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS)) != 0)
+ {
+ count += bcmbal_group_member_info_list_u16_get_packed_length(&this->members);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_COOKIE)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS)) != 0)
+ {
+ count += bcmbal_flow_id_list_u32_get_packed_length(&this->flows);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_OWNER)) != 0)
+ {
+ count += 1;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_cfg_data_unpack(bcmbal_group_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS_CMD)) != 0)
+ {
+ if (!bcmbal_group_member_cmd_unpack(&this->members_cmd, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS)) != 0)
+ {
+ if (!bcmbal_group_member_info_list_u16_unpack(&this->members, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, (uint64_t *) &this->cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS)) != 0)
+ {
+ if (!bcmbal_flow_id_list_u32_unpack(&this->flows, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_group_owner_unpack(&this->owner, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS_CMD)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS)) != 0)
+ {
+ if (!bcmbal_group_member_info_list_u16_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS)) != 0)
+ {
+ if (!bcmbal_flow_id_list_u32_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_group_cfg_data_bounds_check(const bcmbal_group_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_group_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS_CMD)) != 0)
+ {
+ switch (this->members_cmd)
+ {
+ case BCMBAL_GROUP_MEMBER_CMD_ADD_MEMBERS:
+ break;
+ case BCMBAL_GROUP_MEMBER_CMD_REM_MEMBERS:
+ break;
+ case BCMBAL_GROUP_MEMBER_CMD_SET_MEMBERS:
+ break;
+ default:
+ *failed_prop = BCMBAL_GROUP_CFG_ID_MEMBERS_CMD;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_MEMBERS)) != 0)
+ {
+ if (!bcmbal_group_member_info_list_u16_bounds_check(&this->members))
+ {
+ *failed_prop = BCMBAL_GROUP_CFG_ID_MEMBERS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS)) != 0)
+ {
+ if (!bcmbal_flow_id_list_u32_bounds_check(&this->flows))
+ {
+ *failed_prop = BCMBAL_GROUP_CFG_ID_FLOWS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_GROUP_CFG_ID_OWNER)) != 0)
+ {
+ switch (this->owner)
+ {
+ case BCMBAL_GROUP_OWNER_NONE:
+ break;
+ case BCMBAL_GROUP_OWNER_MULTICAST:
+ break;
+ case BCMBAL_GROUP_OWNER_UNICAST:
+ break;
+ default:
+ *failed_prop = BCMBAL_GROUP_CFG_ID_OWNER;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_interface_key_set_default(bcmbal_interface_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_ID)) != 0)
+ {
+ this->intf_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_TYPE)) != 0)
+ {
+ this->intf_type = BCMBAL_INTF_TYPE_NNI;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_key_pack(const bcmbal_interface_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_intf_type_pack(this->intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_interface_key_get_packed_length(const bcmbal_interface_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_key_unpack(bcmbal_interface_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_intf_type_unpack(&this->intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_key_bounds_check(const bcmbal_interface_key *this, bcmbal_presence_mask fields_present, bcmbal_interface_key_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_KEY_ID_INTF_TYPE)) != 0)
+ {
+ switch (this->intf_type)
+ {
+ case BCMBAL_INTF_TYPE_NNI:
+ break;
+ case BCMBAL_INTF_TYPE_PON:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_KEY_ID_INTF_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_interface_cfg_data_set_default(bcmbal_interface_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ this->min_data_agg_port_id = (bcmbal_aggregation_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ this->min_data_svc_port_id = (bcmbal_service_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ this->transceiver_type = BCMBAL_TRX_TYPE_GPON_SPS_43_48;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE)) != 0)
+ {
+ this->ds_miss_mode = BCMBAL_DS_MISS_MODE_DISCARD;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MTU)) != 0)
+ {
+ this->mtu = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL)) != 0)
+ {
+ this->flow_control = BCMBAL_CONTROL_DISABLE;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_TM)) != 0)
+ {
+ this->ds_tm = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_US_TM)) != 0)
+ {
+ this->us_tm = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST)) != 0)
+ {
+ this->sub_term_id_list.len = 0;
+ this->sub_term_id_list.val = NULL;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_cfg_data_pack(const bcmbal_interface_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->min_data_agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->min_data_svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ if (!bcmbal_trx_type_pack(this->transceiver_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE)) != 0)
+ {
+ if (!bcmbal_ds_miss_mode_pack(this->ds_miss_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MTU)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->mtu))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL)) != 0)
+ {
+ if (!bcmbal_control_pack(this->flow_control, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST)) != 0)
+ {
+ if (!bcmbal_sub_id_list_u16_pack(&this->sub_term_id_list, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_interface_cfg_data_get_packed_length(const bcmbal_interface_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MTU)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_US_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST)) != 0)
+ {
+ count += bcmbal_sub_id_list_u16_get_packed_length(&this->sub_term_id_list);
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_cfg_data_unpack(bcmbal_interface_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->min_data_agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->min_data_svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ if (!bcmbal_trx_type_unpack(&this->transceiver_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE)) != 0)
+ {
+ if (!bcmbal_ds_miss_mode_unpack(&this->ds_miss_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MTU)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->mtu))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL)) != 0)
+ {
+ if (!bcmbal_control_unpack(&this->flow_control, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST)) != 0)
+ {
+ if (!bcmbal_sub_id_list_u16_unpack(&this->sub_term_id_list, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_MTU)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST)) != 0)
+ {
+ if (!bcmbal_sub_id_list_u16_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_cfg_data_bounds_check(const bcmbal_interface_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_interface_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_CFG_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_CFG_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ switch (this->transceiver_type)
+ {
+ case BCMBAL_TRX_TYPE_GPON_SPS_43_48:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_LTE_3680_M:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_LTE_3680_P:
+ break;
+ case BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC:
+ break;
+ case BCMBAL_TRX_TYPE_XGPON_LTH_7226_PC:
+ break;
+ case BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_CFG_ID_TRANSCEIVER_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE)) != 0)
+ {
+ switch (this->ds_miss_mode)
+ {
+ case BCMBAL_DS_MISS_MODE_DISCARD:
+ break;
+ case BCMBAL_DS_MISS_MODE_BROADCAST:
+ break;
+ case BCMBAL_DS_MISS_MODE_VID:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_CFG_ID_DS_MISS_MODE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL)) != 0)
+ {
+ switch (this->flow_control)
+ {
+ case BCMBAL_CONTROL_DISABLE:
+ break;
+ case BCMBAL_CONTROL_ENABLE:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_CFG_ID_FLOW_CONTROL;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST)) != 0)
+ {
+ if (!bcmbal_sub_id_list_u16_bounds_check(&this->sub_term_id_list))
+ {
+ *failed_prop = BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_interface_stat_data_set_default(bcmbal_interface_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_PACKETS)) != 0)
+ {
+ this->rx_packets = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_BYTES)) != 0)
+ {
+ this->rx_bytes = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_PACKETS)) != 0)
+ {
+ this->tx_packets = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_BYTES)) != 0)
+ {
+ this->tx_bytes = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_stat_data_pack(const bcmbal_interface_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->rx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->rx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->tx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->tx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_interface_stat_data_get_packed_length(const bcmbal_interface_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_PACKETS)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_BYTES)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_PACKETS)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_BYTES)) != 0)
+ {
+ count += 8;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_stat_data_unpack(bcmbal_interface_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->rx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->rx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->tx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->tx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_stat_data_bounds_check(const bcmbal_interface_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_interface_stat_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_interface_ind_data_set_default(bcmbal_interface_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ this->min_data_agg_port_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ this->min_data_svc_port_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ this->transceiver_type = BCMBAL_TRX_TYPE_GPON_SPS_43_48;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE)) != 0)
+ {
+ this->ds_miss_mode = BCMBAL_DS_MISS_MODE_DISCARD;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MTU)) != 0)
+ {
+ this->mtu = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL)) != 0)
+ {
+ this->flow_control = BCMBAL_CONTROL_DISABLE;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_TM)) != 0)
+ {
+ this->ds_tm = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_US_TM)) != 0)
+ {
+ this->us_tm = (bcmbal_tm_sched_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_ind_data_pack(const bcmbal_interface_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->min_data_agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->min_data_svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ if (!bcmbal_trx_type_pack(this->transceiver_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE)) != 0)
+ {
+ if (!bcmbal_ds_miss_mode_pack(this->ds_miss_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MTU)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->mtu))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL)) != 0)
+ {
+ if (!bcmbal_control_pack(this->flow_control, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_interface_ind_data_get_packed_length(const bcmbal_interface_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MTU)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_US_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_ind_data_unpack(bcmbal_interface_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->min_data_agg_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->min_data_svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ if (!bcmbal_trx_type_unpack(&this->transceiver_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE)) != 0)
+ {
+ if (!bcmbal_ds_miss_mode_unpack(&this->ds_miss_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MTU)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->mtu))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL)) != 0)
+ {
+ if (!bcmbal_control_unpack(&this->flow_control, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_AGG_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MIN_DATA_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_MTU)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_interface_ind_data_bounds_check(const bcmbal_interface_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_interface_ind_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_IND_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_IND_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE)) != 0)
+ {
+ switch (this->transceiver_type)
+ {
+ case BCMBAL_TRX_TYPE_GPON_SPS_43_48:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_LTE_3680_M:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS:
+ break;
+ case BCMBAL_TRX_TYPE_GPON_LTE_3680_P:
+ break;
+ case BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC:
+ break;
+ case BCMBAL_TRX_TYPE_XGPON_LTH_7226_PC:
+ break;
+ case BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_IND_ID_TRANSCEIVER_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE)) != 0)
+ {
+ switch (this->ds_miss_mode)
+ {
+ case BCMBAL_DS_MISS_MODE_DISCARD:
+ break;
+ case BCMBAL_DS_MISS_MODE_BROADCAST:
+ break;
+ case BCMBAL_DS_MISS_MODE_VID:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_IND_ID_DS_MISS_MODE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL)) != 0)
+ {
+ switch (this->flow_control)
+ {
+ case BCMBAL_CONTROL_DISABLE:
+ break;
+ case BCMBAL_CONTROL_ENABLE:
+ break;
+ default:
+ *failed_prop = BCMBAL_INTERFACE_IND_ID_FLOW_CONTROL;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_packet_key_set_default(bcmbal_packet_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_RESERVED)) != 0)
+ {
+ this->reserved = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST)) != 0)
+ {
+ this->packet_send_dest.type = (bcmbal_dest_type) 0;
+ this->packet_send_dest.u.nni.int_id = (bcmbal_intf_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_key_pack(const bcmbal_packet_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_RESERVED)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, this->reserved))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST)) != 0)
+ {
+ if (!bcmbal_dest_pack(&this->packet_send_dest, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_packet_key_get_packed_length(const bcmbal_packet_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_RESERVED)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST)) != 0)
+ {
+ count += bcmbal_dest_get_packed_length(&this->packet_send_dest);
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_key_unpack(bcmbal_packet_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_RESERVED)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->reserved))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST)) != 0)
+ {
+ if (!bcmbal_dest_unpack(&this->packet_send_dest, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_RESERVED)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST)) != 0)
+ {
+ if (!bcmbal_dest_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_key_bounds_check(const bcmbal_packet_key *this, bcmbal_presence_mask fields_present, bcmbal_packet_key_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST)) != 0)
+ {
+ if (!bcmbal_dest_bounds_check(&this->packet_send_dest))
+ {
+ *failed_prop = BCMBAL_PACKET_KEY_ID_PACKET_SEND_DEST;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_packet_cfg_data_set_default(bcmbal_packet_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_ID)) != 0)
+ {
+ this->flow_id = (bcmbal_flow_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_TYPE)) != 0)
+ {
+ this->flow_type = (bcmbal_flow_type) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_ID)) != 0)
+ {
+ this->intf_id = (bcmbal_intf_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_TYPE)) != 0)
+ {
+ this->intf_type = BCMBAL_INTF_TYPE_NNI;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_SVC_PORT)) != 0)
+ {
+ this->svc_port = (bcmbal_service_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_COOKIE)) != 0)
+ {
+ this->flow_cookie = (bcmbal_cookie) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_PKT)) != 0)
+ {
+ this->pkt.len = 0;
+ this->pkt.val = NULL;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_cfg_data_pack(const bcmbal_packet_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->flow_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_flow_type_pack(this->flow_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_intf_type_pack(this->intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_SVC_PORT)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->svc_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, (uint64_t) this->flow_cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_pack(&this->pkt, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_packet_cfg_data_get_packed_length(const bcmbal_packet_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_SVC_PORT)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_COOKIE)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_PKT)) != 0)
+ {
+ count += bcmbal_u8_list_u32_get_packed_length(&this->pkt);
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_cfg_data_unpack(bcmbal_packet_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->flow_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_flow_type_unpack(&this->flow_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_intf_type_unpack(&this->intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_SVC_PORT)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->svc_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, (uint64_t *) &this->flow_cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_unpack(&this->pkt, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_SVC_PORT)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_cfg_data_bounds_check(const bcmbal_packet_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_packet_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_FLOW_TYPE)) != 0)
+ {
+ switch (this->flow_type)
+ {
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ break;
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ break;
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ break;
+ case BCMBAL_FLOW_TYPE_MULTICAST:
+ break;
+ default:
+ *failed_prop = BCMBAL_PACKET_CFG_ID_FLOW_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_INTF_TYPE)) != 0)
+ {
+ switch (this->intf_type)
+ {
+ case BCMBAL_INTF_TYPE_NNI:
+ break;
+ case BCMBAL_INTF_TYPE_PON:
+ break;
+ default:
+ *failed_prop = BCMBAL_PACKET_CFG_ID_INTF_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_CFG_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_bounds_check(&this->pkt))
+ {
+ *failed_prop = BCMBAL_PACKET_CFG_ID_PKT;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_packet_ind_data_set_default(bcmbal_packet_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_ID)) != 0)
+ {
+ this->flow_id = (bcmbal_flow_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_TYPE)) != 0)
+ {
+ this->flow_type = (bcmbal_flow_type) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_ID)) != 0)
+ {
+ this->intf_id = (bcmbal_intf_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_TYPE)) != 0)
+ {
+ this->intf_type = BCMBAL_INTF_TYPE_NNI;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_SVC_PORT)) != 0)
+ {
+ this->svc_port = (bcmbal_service_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_COOKIE)) != 0)
+ {
+ this->flow_cookie = (bcmbal_cookie) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_PKT)) != 0)
+ {
+ this->pkt.len = 0;
+ this->pkt.val = NULL;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_ind_data_pack(const bcmbal_packet_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->flow_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_flow_type_pack(this->flow_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_intf_type_pack(this->intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_SVC_PORT)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->svc_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, (uint64_t) this->flow_cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_pack(&this->pkt, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_packet_ind_data_get_packed_length(const bcmbal_packet_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_TYPE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_SVC_PORT)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_COOKIE)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_PKT)) != 0)
+ {
+ count += bcmbal_u8_list_u32_get_packed_length(&this->pkt);
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_ind_data_unpack(bcmbal_packet_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->flow_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_flow_type_unpack(&this->flow_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_intf_type_unpack(&this->intf_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_SVC_PORT)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->svc_port))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, (uint64_t *) &this->flow_cookie))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_unpack(&this->pkt, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_SVC_PORT)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_COOKIE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_packet_ind_data_bounds_check(const bcmbal_packet_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_packet_ind_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_FLOW_TYPE)) != 0)
+ {
+ switch (this->flow_type)
+ {
+ case BCMBAL_FLOW_TYPE_UPSTREAM:
+ break;
+ case BCMBAL_FLOW_TYPE_DOWNSTREAM:
+ break;
+ case BCMBAL_FLOW_TYPE_BROADCAST:
+ break;
+ case BCMBAL_FLOW_TYPE_MULTICAST:
+ break;
+ default:
+ *failed_prop = BCMBAL_PACKET_IND_ID_FLOW_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_INTF_TYPE)) != 0)
+ {
+ switch (this->intf_type)
+ {
+ case BCMBAL_INTF_TYPE_NNI:
+ break;
+ case BCMBAL_INTF_TYPE_PON:
+ break;
+ default:
+ *failed_prop = BCMBAL_PACKET_IND_ID_INTF_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_PACKET_IND_ID_PKT)) != 0)
+ {
+ if (!bcmbal_u8_list_u32_bounds_check(&this->pkt))
+ {
+ *failed_prop = BCMBAL_PACKET_IND_ID_PKT;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_subscriber_terminal_key_set_default(bcmbal_subscriber_terminal_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID)) != 0)
+ {
+ this->sub_term_id = (bcmbal_sub_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID)) != 0)
+ {
+ this->intf_id = (bcmbal_intf_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_key_pack(const bcmbal_subscriber_terminal_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_subscriber_terminal_key_get_packed_length(const bcmbal_subscriber_terminal_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_key_unpack(bcmbal_subscriber_terminal_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->sub_term_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->intf_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_SUB_TERM_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_KEY_ID_INTF_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_key_bounds_check(const bcmbal_subscriber_terminal_key *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_key_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_subscriber_terminal_cfg_data_set_default(bcmbal_subscriber_terminal_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER)) != 0)
+ {
+ memset(this->serial_number.vendor_id, 0, sizeof(this->serial_number.vendor_id));
+ memset(this->serial_number.vendor_specific, 0, sizeof(this->serial_number.vendor_specific));
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD)) != 0)
+ {
+ memset(this->password.arr, 0, sizeof(this->password.arr));
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID)) != 0)
+ {
+ memset(this->registration_id.arr, 0, sizeof(this->registration_id.arr));
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ this->svc_port_id = (bcmbal_service_port_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS)) != 0)
+ {
+ bcmos_mac_address_init(&this->mac_address);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM)) != 0)
+ {
+ this->ds_tm = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM)) != 0)
+ {
+ this->us_tm = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) != 0)
+ {
+ this->svc_port_id_list.len = 0;
+ this->svc_port_id_list.val = NULL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST)) != 0)
+ {
+ this->agg_port_id_list.len = 0;
+ this->agg_port_id_list.val = NULL;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_pack(const bcmbal_subscriber_terminal_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_serial_number_pack(&this->serial_number, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_password_pack(&this->password, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_registration_id_pack(&this->registration_id, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, (uint16_t) this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS)) != 0)
+ {
+ if (!bcmbal_buf_write_mac_address(buf, this->mac_address))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_service_port_id_list_u8_pack(&this->svc_port_id_list, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_aggregation_port_id_list_u8_pack(&this->agg_port_id_list, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_subscriber_terminal_cfg_data_get_packed_length(const bcmbal_subscriber_terminal_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD)) != 0)
+ {
+ count += 10;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID)) != 0)
+ {
+ count += 36;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS)) != 0)
+ {
+ count += 6;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) != 0)
+ {
+ count += bcmbal_service_port_id_list_u8_get_packed_length(&this->svc_port_id_list);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST)) != 0)
+ {
+ count += bcmbal_aggregation_port_id_list_u8_get_packed_length(&this->agg_port_id_list);
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_unpack(bcmbal_subscriber_terminal_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_serial_number_unpack(&this->serial_number, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_password_unpack(&this->password, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_registration_id_unpack(&this->registration_id, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, (uint16_t *) &this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS)) != 0)
+ {
+ if (!bcmbal_buf_read_mac_address(buf, &this->mac_address))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_service_port_id_list_u8_unpack(&this->svc_port_id_list, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_aggregation_port_id_list_u8_unpack(&this->agg_port_id_list, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 10))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 36))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_MAC_ADDRESS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 6))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_service_port_id_list_u8_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_aggregation_port_id_list_u8_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_bounds_check(const bcmbal_subscriber_terminal_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_serial_number_bounds_check(&this->serial_number))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SERIAL_NUMBER;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_password_bounds_check(&this->password))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_PASSWORD;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_registration_id_bounds_check(&this->registration_id))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_REGISTRATION_ID;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_service_port_id_list_u8_bounds_check(&this->svc_port_id_list))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST)) != 0)
+ {
+ if (!bcmbal_aggregation_port_id_list_u8_bounds_check(&this->agg_port_id_list))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_subscriber_terminal_stat_data_set_default(bcmbal_subscriber_terminal_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS)) != 0)
+ {
+ this->rx_packets = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES)) != 0)
+ {
+ this->rx_bytes = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS)) != 0)
+ {
+ this->tx_packets = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES)) != 0)
+ {
+ this->tx_bytes = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_stat_data_pack(const bcmbal_subscriber_terminal_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->rx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->rx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->tx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->tx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_subscriber_terminal_stat_data_get_packed_length(const bcmbal_subscriber_terminal_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES)) != 0)
+ {
+ count += 8;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_stat_data_unpack(bcmbal_subscriber_terminal_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->rx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->rx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->tx_packets))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->tx_bytes))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_RX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_PACKETS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_STAT_ID_TX_BYTES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_stat_data_bounds_check(const bcmbal_subscriber_terminal_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_stat_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_subscriber_terminal_ind_data_set_default(bcmbal_subscriber_terminal_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ this->admin_state = (bcmbal_state) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ this->oper_status = (bcmbal_status) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER)) != 0)
+ {
+ memset(this->serial_number.vendor_id, 0, sizeof(this->serial_number.vendor_id));
+ memset(this->serial_number.vendor_specific, 0, sizeof(this->serial_number.vendor_specific));
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD)) != 0)
+ {
+ memset(this->password.arr, 0, sizeof(this->password.arr));
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID)) != 0)
+ {
+ memset(this->registration_id.arr, 0, sizeof(this->registration_id.arr));
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ this->svc_port_id = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS)) != 0)
+ {
+ bcmos_mac_address_init(&this->mac_address);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM)) != 0)
+ {
+ this->ds_tm = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM)) != 0)
+ {
+ this->us_tm = (bcmbal_tm_sched_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_ind_data_pack(const bcmbal_subscriber_terminal_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_pack(this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_pack(this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_serial_number_pack(&this->serial_number, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_password_pack(&this->password, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_registration_id_pack(&this->registration_id, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u16(buf, this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS)) != 0)
+ {
+ if (!bcmbal_buf_write_mac_address(buf, this->mac_address))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_subscriber_terminal_ind_data_get_packed_length(const bcmbal_subscriber_terminal_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD)) != 0)
+ {
+ count += 10;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID)) != 0)
+ {
+ count += 36;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ count += 2;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS)) != 0)
+ {
+ count += 6;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_ind_data_unpack(bcmbal_subscriber_terminal_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_state_unpack(&this->admin_state, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_status_unpack(&this->oper_status, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_serial_number_unpack(&this->serial_number, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_password_unpack(&this->password, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_registration_id_unpack(&this->registration_id, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u16(buf, &this->svc_port_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS)) != 0)
+ {
+ if (!bcmbal_buf_read_mac_address(buf, &this->mac_address))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->ds_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->us_tm))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 10))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 36))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SVC_PORT_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 2))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_MAC_ADDRESS)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 6))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_DS_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_US_TM)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_subscriber_terminal_ind_data_bounds_check(const bcmbal_subscriber_terminal_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_ind_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE)) != 0)
+ {
+ switch (this->admin_state)
+ {
+ case BCMBAL_STATE_UP:
+ break;
+ case BCMBAL_STATE_DOWN:
+ break;
+ case BCMBAL_STATE_TESTING:
+ break;
+ default:
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_ADMIN_STATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS)) != 0)
+ {
+ switch (this->oper_status)
+ {
+ case BCMBAL_STATUS_UP:
+ break;
+ case BCMBAL_STATUS_DOWN:
+ break;
+ case BCMBAL_STATUS_TESTING:
+ break;
+ case BCMBAL_STATUS_NOT_PRESENT:
+ break;
+ case BCMBAL_STATUS_LOWER_LAYER_DOWN:
+ break;
+ case BCMBAL_STATUS_UNKNOWN:
+ break;
+ default:
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_OPER_STATUS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER)) != 0)
+ {
+ if (!bcmbal_serial_number_bounds_check(&this->serial_number))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_SERIAL_NUMBER;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD)) != 0)
+ {
+ if (!bcmbal_password_bounds_check(&this->password))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_PASSWORD;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID)) != 0)
+ {
+ if (!bcmbal_registration_id_bounds_check(&this->registration_id))
+ {
+ *failed_prop = BCMBAL_SUBSCRIBER_TERMINAL_IND_ID_REGISTRATION_ID;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_queue_key_set_default(bcmbal_tm_queue_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID)) != 0)
+ {
+ this->sched_id = (bcmbal_tm_sched_id) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR)) != 0)
+ {
+ this->sched_dir = (bcmbal_tm_sched_dir) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_ID)) != 0)
+ {
+ this->id = (bcmbal_tm_queue_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_key_pack(const bcmbal_tm_queue_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->sched_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR)) != 0)
+ {
+ if (!bcmbal_tm_sched_dir_pack(this->sched_dir, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_queue_key_get_packed_length(const bcmbal_tm_queue_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_ID)) != 0)
+ {
+ count += 1;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_key_unpack(bcmbal_tm_queue_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->sched_id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR)) != 0)
+ {
+ if (!bcmbal_tm_sched_dir_unpack(&this->sched_dir, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_key_bounds_check(const bcmbal_tm_queue_key *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_key_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR)) != 0)
+ {
+ switch (this->sched_dir)
+ {
+ case BCMBAL_TM_SCHED_DIR_US:
+ break;
+ case BCMBAL_TM_SCHED_DIR_DS:
+ break;
+ default:
+ *failed_prop = BCMBAL_TM_QUEUE_KEY_ID_SCHED_DIR;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_queue_cfg_data_set_default(bcmbal_tm_queue_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_PRIORITY)) != 0)
+ {
+ this->priority = (bcmbal_tm_priority) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_WEIGHT)) != 0)
+ {
+ this->weight = (bcmbal_tm_weight) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_RATE)) != 0)
+ {
+ this->rate.presence_mask = (bcmbal_tm_shaping_id) 0;
+ this->rate.sbr = 0;
+ this->rate.pbr = 0;
+ this->rate.burst = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_BAC)) != 0)
+ {
+ this->bac.type = BCMBAL_TM_BAC_TYPE_TAILDROP;
+ this->bac.u.taildrop.max_size = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE)) != 0)
+ {
+ this->creation_mode = BCMBAL_TM_CREATION_MODE_MANUAL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT)) != 0)
+ {
+ this->ref_count = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_cfg_data_pack(const bcmbal_tm_queue_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_WEIGHT)) != 0)
+ {
+ if (!bcmbal_buf_write_u8(buf, (uint8_t) this->weight))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_pack(&this->rate, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_BAC)) != 0)
+ {
+ if (!bcmbal_tm_bac_pack(&this->bac, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE)) != 0)
+ {
+ if (!bcmbal_tm_creation_mode_pack(this->creation_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT)) != 0)
+ {
+ if (!bcmbal_buf_write_u8(buf, this->ref_count))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_queue_cfg_data_get_packed_length(const bcmbal_tm_queue_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_PRIORITY)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_WEIGHT)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_RATE)) != 0)
+ {
+ count += bcmbal_tm_shaping_get_packed_length(&this->rate);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_BAC)) != 0)
+ {
+ count += bcmbal_tm_bac_get_packed_length(&this->bac);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT)) != 0)
+ {
+ count += 1;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_cfg_data_unpack(bcmbal_tm_queue_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->priority))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_WEIGHT)) != 0)
+ {
+ if (!bcmbal_buf_read_u8(buf, (uint8_t *) &this->weight))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_unpack(&this->rate, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_BAC)) != 0)
+ {
+ if (!bcmbal_tm_bac_unpack(&this->bac, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE)) != 0)
+ {
+ if (!bcmbal_tm_creation_mode_unpack(&this->creation_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT)) != 0)
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->ref_count))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_PRIORITY)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_WEIGHT)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_BAC)) != 0)
+ {
+ if (!bcmbal_tm_bac_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_cfg_data_bounds_check(const bcmbal_tm_queue_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_bounds_check(&this->rate))
+ {
+ *failed_prop = BCMBAL_TM_QUEUE_CFG_ID_RATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_BAC)) != 0)
+ {
+ if (!bcmbal_tm_bac_bounds_check(&this->bac))
+ {
+ *failed_prop = BCMBAL_TM_QUEUE_CFG_ID_BAC;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE)) != 0)
+ {
+ switch (this->creation_mode)
+ {
+ case BCMBAL_TM_CREATION_MODE_MANUAL:
+ break;
+ case BCMBAL_TM_CREATION_MODE_AUTO:
+ break;
+ default:
+ *failed_prop = BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_queue_stat_data_set_default(bcmbal_tm_queue_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK)) != 0)
+ {
+ this->packets_ok = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK)) != 0)
+ {
+ this->bytes_ok = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED)) != 0)
+ {
+ this->packets_discarded = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED)) != 0)
+ {
+ this->bytes_discarded = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_stat_data_pack(const bcmbal_tm_queue_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->packets_ok))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->bytes_ok))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->packets_discarded))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED)) != 0)
+ {
+ if (!bcmbal_buf_write_u64(buf, this->bytes_discarded))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_queue_stat_data_get_packed_length(const bcmbal_tm_queue_stat_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED)) != 0)
+ {
+ count += 8;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED)) != 0)
+ {
+ count += 8;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_stat_data_unpack(bcmbal_tm_queue_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->packets_ok))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->bytes_ok))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->packets_discarded))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED)) != 0)
+ {
+ if (!bcmbal_buf_read_u64(buf, &this->bytes_discarded))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_OK)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_OK)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_PACKETS_DISCARDED)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_STAT_ID_BYTES_DISCARDED)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 8))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_stat_data_bounds_check(const bcmbal_tm_queue_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_stat_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_queue_ind_data_set_default(bcmbal_tm_queue_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_IND_ID_RET)) != 0)
+ {
+ this->ret = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ind_data_pack(const bcmbal_tm_queue_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_IND_ID_RET)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, this->ret))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_queue_ind_data_get_packed_length(const bcmbal_tm_queue_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_IND_ID_RET)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ind_data_unpack(bcmbal_tm_queue_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_IND_ID_RET)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->ret))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_QUEUE_IND_ID_RET)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_queue_ind_data_bounds_check(const bcmbal_tm_queue_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_ind_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_sched_key_set_default(bcmbal_tm_sched_key *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_DIR)) != 0)
+ {
+ this->dir = (bcmbal_tm_sched_dir) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_ID)) != 0)
+ {
+ this->id = (bcmbal_tm_sched_id) 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_key_pack(const bcmbal_tm_sched_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_DIR)) != 0)
+ {
+ if (!bcmbal_tm_sched_dir_pack(this->dir, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_ID)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, (uint32_t) this->id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_sched_key_get_packed_length(const bcmbal_tm_sched_key *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_DIR)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_ID)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_key_unpack(bcmbal_tm_sched_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_DIR)) != 0)
+ {
+ if (!bcmbal_tm_sched_dir_unpack(&this->dir, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_ID)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, (uint32_t *) &this->id))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_DIR)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_ID)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_key_bounds_check(const bcmbal_tm_sched_key *this, bcmbal_presence_mask fields_present, bcmbal_tm_sched_key_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_KEY_ID_DIR)) != 0)
+ {
+ switch (this->dir)
+ {
+ case BCMBAL_TM_SCHED_DIR_US:
+ break;
+ case BCMBAL_TM_SCHED_DIR_DS:
+ break;
+ default:
+ *failed_prop = BCMBAL_TM_SCHED_KEY_ID_DIR;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_sched_cfg_data_set_default(bcmbal_tm_sched_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_OWNER)) != 0)
+ {
+ this->owner.type = BCMBAL_TM_SCHED_OWNER_TYPE_UNDEFINED;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE)) != 0)
+ {
+ this->sched_type = BCMBAL_TM_SCHED_TYPE_NONE;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT)) != 0)
+ {
+ this->sched_parent.presence_mask = (bcmbal_tm_sched_parent_id) 0;
+ this->sched_parent.sched_id = (bcmbal_tm_sched_id) 0;
+ this->sched_parent.priority = (bcmbal_tm_priority) 0;
+ this->sched_parent.weight = (bcmbal_tm_weight) 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE)) != 0)
+ {
+ this->sched_child_type = BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_RATE)) != 0)
+ {
+ this->rate.presence_mask = (bcmbal_tm_shaping_id) 0;
+ this->rate.sbr = 0;
+ this->rate.pbr = 0;
+ this->rate.burst = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA)) != 0)
+ {
+ this->tcont_sla.presence_mask = (bcmbal_tm_tcont_sla_id) 0;
+ this->tcont_sla.extra_bw_elig = BCMBAL_EXTRA_BW_ELIGIBILITY_TYPE_NONE;
+ this->tcont_sla.nrt_cbr = 0;
+ this->tcont_sla.rt_cbr = 0;
+ this->tcont_sla.rt_profile = 0;
+ this->tcont_sla.nrt_profile = 0;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE)) != 0)
+ {
+ this->creation_mode = BCMBAL_TM_CREATION_MODE_MANUAL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) != 0)
+ {
+ this->queues.len = 0;
+ this->queues.val = NULL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS)) != 0)
+ {
+ this->sub_scheds.len = 0;
+ this->sub_scheds.val = NULL;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES)) != 0)
+ {
+ this->num_priorities = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_cfg_data_pack(const bcmbal_tm_sched_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_tm_sched_owner_pack(&this->owner, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE)) != 0)
+ {
+ if (!bcmbal_tm_sched_type_pack(this->sched_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT)) != 0)
+ {
+ if (!bcmbal_tm_sched_parent_pack(&this->sched_parent, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE)) != 0)
+ {
+ if (!bcmbal_tm_sched_child_type_pack(this->sched_child_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_pack(&this->rate, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA)) != 0)
+ {
+ if (!bcmbal_tm_tcont_sla_pack(&this->tcont_sla, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE)) != 0)
+ {
+ if (!bcmbal_tm_creation_mode_pack(this->creation_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) != 0)
+ {
+ if (!bcmbal_tm_queue_id_list_u8_pack(&this->queues, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS)) != 0)
+ {
+ if (!bcmbal_tm_sched_id_list_u8_pack(&this->sub_scheds, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES)) != 0)
+ {
+ if (!bcmbal_buf_write_u8(buf, this->num_priorities))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_sched_cfg_data_get_packed_length(const bcmbal_tm_sched_cfg_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_OWNER)) != 0)
+ {
+ count += bcmbal_tm_sched_owner_get_packed_length(&this->owner);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT)) != 0)
+ {
+ count += bcmbal_tm_sched_parent_get_packed_length(&this->sched_parent);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_RATE)) != 0)
+ {
+ count += bcmbal_tm_shaping_get_packed_length(&this->rate);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA)) != 0)
+ {
+ count += bcmbal_tm_tcont_sla_get_packed_length(&this->tcont_sla);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE)) != 0)
+ {
+ count += 1;
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) != 0)
+ {
+ count += bcmbal_tm_queue_id_list_u8_get_packed_length(&this->queues);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS)) != 0)
+ {
+ count += bcmbal_tm_sched_id_list_u8_get_packed_length(&this->sub_scheds);
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES)) != 0)
+ {
+ count += 1;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_cfg_data_unpack(bcmbal_tm_sched_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_tm_sched_owner_unpack(&this->owner, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE)) != 0)
+ {
+ if (!bcmbal_tm_sched_type_unpack(&this->sched_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT)) != 0)
+ {
+ if (!bcmbal_tm_sched_parent_unpack(&this->sched_parent, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE)) != 0)
+ {
+ if (!bcmbal_tm_sched_child_type_unpack(&this->sched_child_type, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_unpack(&this->rate, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA)) != 0)
+ {
+ if (!bcmbal_tm_tcont_sla_unpack(&this->tcont_sla, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE)) != 0)
+ {
+ if (!bcmbal_tm_creation_mode_unpack(&this->creation_mode, buf))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) != 0)
+ {
+ if (!bcmbal_tm_queue_id_list_u8_unpack(&this->queues, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS)) != 0)
+ {
+ if (!bcmbal_tm_sched_id_list_u8_unpack(&this->sub_scheds, buf, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES)) != 0)
+ {
+ if (!bcmbal_buf_read_u8(buf, &this->num_priorities))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_tm_sched_owner_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT)) != 0)
+ {
+ if (!bcmbal_tm_sched_parent_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA)) != 0)
+ {
+ if (!bcmbal_tm_tcont_sla_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) != 0)
+ {
+ if (!bcmbal_tm_queue_id_list_u8_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS)) != 0)
+ {
+ if (!bcmbal_tm_sched_id_list_u8_scan(packed, extra_mem))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_NUM_PRIORITIES)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 1))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_cfg_data_bounds_check(const bcmbal_tm_sched_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_sched_cfg_id *failed_prop)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_OWNER)) != 0)
+ {
+ if (!bcmbal_tm_sched_owner_bounds_check(&this->owner))
+ {
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_OWNER;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE)) != 0)
+ {
+ switch (this->sched_type)
+ {
+ case BCMBAL_TM_SCHED_TYPE_NONE:
+ break;
+ case BCMBAL_TM_SCHED_TYPE_WFQ:
+ break;
+ case BCMBAL_TM_SCHED_TYPE_SP:
+ break;
+ case BCMBAL_TM_SCHED_TYPE_SP_WFQ:
+ break;
+ default:
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_SCHED_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT)) != 0)
+ {
+ if (!bcmbal_tm_sched_parent_bounds_check(&this->sched_parent))
+ {
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_SCHED_PARENT;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE)) != 0)
+ {
+ switch (this->sched_child_type)
+ {
+ case BCMBAL_TM_SCHED_CHILD_TYPE_QUEUE:
+ break;
+ case BCMBAL_TM_SCHED_CHILD_TYPE_SCHED:
+ break;
+ default:
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_SCHED_CHILD_TYPE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_RATE)) != 0)
+ {
+ if (!bcmbal_tm_shaping_bounds_check(&this->rate))
+ {
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_RATE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA)) != 0)
+ {
+ if (!bcmbal_tm_tcont_sla_bounds_check(&this->tcont_sla))
+ {
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_TCONT_SLA;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE)) != 0)
+ {
+ switch (this->creation_mode)
+ {
+ case BCMBAL_TM_CREATION_MODE_MANUAL:
+ break;
+ case BCMBAL_TM_CREATION_MODE_AUTO:
+ break;
+ default:
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) != 0)
+ {
+ if (!bcmbal_tm_queue_id_list_u8_bounds_check(&this->queues))
+ {
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_QUEUES;
+ return BCMOS_FALSE;
+ }
+ }
+
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS)) != 0)
+ {
+ if (!bcmbal_tm_sched_id_list_u8_bounds_check(&this->sub_scheds))
+ {
+ *failed_prop = BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS;
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+void bcmbal_tm_sched_ind_data_set_default(bcmbal_tm_sched_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_IND_ID_RET)) != 0)
+ {
+ this->ret = 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_ind_data_pack(const bcmbal_tm_sched_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_IND_ID_RET)) != 0)
+ {
+ if (!bcmbal_buf_write_u32(buf, this->ret))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+uint32_t bcmbal_tm_sched_ind_data_get_packed_length(const bcmbal_tm_sched_ind_data *this, bcmbal_presence_mask fields_present)
+{
+ uint32_t count = 0;
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_IND_ID_RET)) != 0)
+ {
+ count += 4;
+ }
+
+ return count;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_ind_data_unpack(bcmbal_tm_sched_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_IND_ID_RET)) != 0)
+ {
+ if (!bcmbal_buf_read_u32(buf, &this->ret))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present)
+{
+ if ((fields_present & (1ULL << BCMBAL_TM_SCHED_IND_ID_RET)) != 0)
+ {
+ if (!bcmbal_buf_skip(packed, 4))
+ {
+ return BCMOS_FALSE;
+ }
+ }
+
+ return BCMOS_TRUE;
+}
+
+/******************************************************************************/
+bcmos_bool bcmbal_tm_sched_ind_data_bounds_check(const bcmbal_tm_sched_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_sched_ind_id *failed_prop)
+{
+ return BCMOS_TRUE;
+}
+
+bcmos_bool bcmbal_obj_has_tag(bcmbal_obj_id obj, bcmbal_obj_tag tag)
+{
+ switch (obj)
+ {
+ default:
+ return BCMOS_FALSE;
+ }
+}
diff --git a/bal_release/src/lib/libobjmsg/bal_model_funcs.h b/bal_release/src/lib/libobjmsg/bal_model_funcs.h
new file mode 100644
index 0000000..a0f5dd0
--- /dev/null
+++ b/bal_release/src/lib/libobjmsg/bal_model_funcs.h
@@ -0,0 +1,3441 @@
+#ifndef BAL_MODEL_FUNCS
+#define BAL_MODEL_FUNCS
+
+#include "bcmos_system.h"
+#include "bcmos_errno.h"
+#include "bal_buf.h"
+#include "bal_model_ids.h"
+#include "bal_model_types.h"
+
+/** Packs a bcmbal_access_terminal_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_access_terminal_cfg_id_pack(bcmbal_access_terminal_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_access_terminal_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_access_terminal_cfg_id_unpack(bcmbal_access_terminal_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_access_terminal_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_access_terminal_ind_id_pack(bcmbal_access_terminal_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_access_terminal_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_access_terminal_ind_id_unpack(bcmbal_access_terminal_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_access_terminal_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_access_terminal_key_id_pack(bcmbal_access_terminal_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_access_terminal_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_access_terminal_key_id_unpack(bcmbal_access_terminal_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_action_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_action_id_pack(bcmbal_action_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_action_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_action_id_unpack(bcmbal_action_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_action_cmd_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_action_cmd_id_pack(bcmbal_action_cmd_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_action_cmd_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_action_cmd_id_unpack(bcmbal_action_cmd_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_classifier_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_classifier_id_pack(bcmbal_classifier_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_classifier_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_classifier_id_unpack(bcmbal_classifier_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_pkt_tag_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_pkt_tag_type_pack(bcmbal_pkt_tag_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_pkt_tag_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_pkt_tag_type_unpack(bcmbal_pkt_tag_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_control to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_control_pack(bcmbal_control this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_control from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_control_unpack(bcmbal_control *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_dest_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_dest_type_pack(bcmbal_dest_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_dest_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_dest_type_unpack(bcmbal_dest_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_ds_miss_mode to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_ds_miss_mode_pack(bcmbal_ds_miss_mode this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_ds_miss_mode from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_ds_miss_mode_unpack(bcmbal_ds_miss_mode *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_extra_bw_eligibility_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_extra_bw_eligibility_type_pack(bcmbal_extra_bw_eligibility_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_extra_bw_eligibility_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_extra_bw_eligibility_type_unpack(bcmbal_extra_bw_eligibility_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_flow_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_flow_cfg_id_pack(bcmbal_flow_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_flow_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_flow_cfg_id_unpack(bcmbal_flow_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_flow_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_flow_ind_id_pack(bcmbal_flow_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_flow_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_flow_ind_id_unpack(bcmbal_flow_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_flow_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_flow_key_id_pack(bcmbal_flow_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_flow_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_flow_key_id_unpack(bcmbal_flow_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_flow_stat_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_flow_stat_id_pack(bcmbal_flow_stat_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_flow_stat_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_flow_stat_id_unpack(bcmbal_flow_stat_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_flow_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_flow_type_pack(bcmbal_flow_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_flow_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_flow_type_unpack(bcmbal_flow_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_group_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_group_cfg_id_pack(bcmbal_group_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_group_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_group_cfg_id_unpack(bcmbal_group_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_group_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_group_key_id_pack(bcmbal_group_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_group_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_group_key_id_unpack(bcmbal_group_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_group_member_cmd to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_group_member_cmd_pack(bcmbal_group_member_cmd this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_group_member_cmd from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_group_member_cmd_unpack(bcmbal_group_member_cmd *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_group_owner to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_group_owner_pack(bcmbal_group_owner this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_group_owner from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_group_owner_unpack(bcmbal_group_owner *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_interface_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_interface_cfg_id_pack(bcmbal_interface_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_interface_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_interface_cfg_id_unpack(bcmbal_interface_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_interface_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_interface_ind_id_pack(bcmbal_interface_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_interface_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_interface_ind_id_unpack(bcmbal_interface_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_interface_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_interface_key_id_pack(bcmbal_interface_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_interface_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_interface_key_id_unpack(bcmbal_interface_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_interface_stat_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_interface_stat_id_pack(bcmbal_interface_stat_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_interface_stat_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_interface_stat_id_unpack(bcmbal_interface_stat_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_intf_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_intf_type_pack(bcmbal_intf_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_intf_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_intf_type_unpack(bcmbal_intf_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_iwf_mode to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_iwf_mode_pack(bcmbal_iwf_mode this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_iwf_mode from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_iwf_mode_unpack(bcmbal_iwf_mode *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_packet_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_packet_cfg_id_pack(bcmbal_packet_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_packet_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_packet_cfg_id_unpack(bcmbal_packet_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_packet_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_packet_ind_id_pack(bcmbal_packet_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_packet_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_packet_ind_id_unpack(bcmbal_packet_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_packet_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_packet_key_id_pack(bcmbal_packet_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_packet_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_packet_key_id_unpack(bcmbal_packet_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_sla_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_sla_id_pack(bcmbal_sla_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_sla_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_sla_id_unpack(bcmbal_sla_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_state to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_state_pack(bcmbal_state this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_state from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_state_unpack(bcmbal_state *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_status to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_status_pack(bcmbal_status this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_status from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_status_unpack(bcmbal_status *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_subscriber_terminal_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_cfg_id_pack(bcmbal_subscriber_terminal_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_subscriber_terminal_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_cfg_id_unpack(bcmbal_subscriber_terminal_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_subscriber_terminal_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_ind_id_pack(bcmbal_subscriber_terminal_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_subscriber_terminal_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_ind_id_unpack(bcmbal_subscriber_terminal_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_subscriber_terminal_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_key_id_pack(bcmbal_subscriber_terminal_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_subscriber_terminal_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_key_id_unpack(bcmbal_subscriber_terminal_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_subscriber_terminal_stat_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_stat_id_pack(bcmbal_subscriber_terminal_stat_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_subscriber_terminal_stat_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_subscriber_terminal_stat_id_unpack(bcmbal_subscriber_terminal_stat_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_bac_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_bac_type_pack(bcmbal_tm_bac_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_bac_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_bac_type_unpack(bcmbal_tm_bac_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_creation_mode to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_creation_mode_pack(bcmbal_tm_creation_mode this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_creation_mode from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_creation_mode_unpack(bcmbal_tm_creation_mode *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_queue_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_queue_cfg_id_pack(bcmbal_tm_queue_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_queue_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_queue_cfg_id_unpack(bcmbal_tm_queue_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_queue_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_queue_ind_id_pack(bcmbal_tm_queue_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_queue_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_queue_ind_id_unpack(bcmbal_tm_queue_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_queue_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_queue_key_id_pack(bcmbal_tm_queue_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_queue_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_queue_key_id_unpack(bcmbal_tm_queue_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_queue_stat_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_queue_stat_id_pack(bcmbal_tm_queue_stat_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_queue_stat_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_queue_stat_id_unpack(bcmbal_tm_queue_stat_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_cfg_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_cfg_id_pack(bcmbal_tm_sched_cfg_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_cfg_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_cfg_id_unpack(bcmbal_tm_sched_cfg_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_child_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_child_type_pack(bcmbal_tm_sched_child_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_child_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_child_type_unpack(bcmbal_tm_sched_child_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_dir to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_dir_pack(bcmbal_tm_sched_dir this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_dir from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_dir_unpack(bcmbal_tm_sched_dir *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_ind_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_ind_id_pack(bcmbal_tm_sched_ind_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_ind_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_ind_id_unpack(bcmbal_tm_sched_ind_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_key_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_key_id_pack(bcmbal_tm_sched_key_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_key_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_key_id_unpack(bcmbal_tm_sched_key_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_owner_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_owner_type_pack(bcmbal_tm_sched_owner_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_owner_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_owner_type_unpack(bcmbal_tm_sched_owner_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_owner_agg_port_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_owner_agg_port_id_pack(bcmbal_tm_sched_owner_agg_port_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_owner_agg_port_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_owner_agg_port_id_unpack(bcmbal_tm_sched_owner_agg_port_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_parent_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_parent_id_pack(bcmbal_tm_sched_parent_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_parent_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_parent_id_unpack(bcmbal_tm_sched_parent_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_sched_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_sched_type_pack(bcmbal_tm_sched_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_sched_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_sched_type_unpack(bcmbal_tm_sched_type *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_shaping_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_shaping_id_pack(bcmbal_tm_shaping_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_shaping_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_shaping_id_unpack(bcmbal_tm_shaping_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_tm_tcont_sla_id to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_tm_tcont_sla_id_pack(bcmbal_tm_tcont_sla_id this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_tcont_sla_id from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_tm_tcont_sla_id_unpack(bcmbal_tm_tcont_sla_id *this, bcmbal_buf *buf);
+
+/** Packs a bcmbal_trx_type to bytes
+ *
+ * \param this The enumeration to pack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the pack was successful
+ */
+bcmos_bool bcmbal_trx_type_pack(bcmbal_trx_type this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_trx_type from bytes
+ *
+ * \param this Pointer to the enumeration to unpack
+ * \param buf Pointer to the buffer to write to
+ * \return Whether or not the unpack was successful
+ */
+bcmos_bool bcmbal_trx_type_unpack(bcmbal_trx_type *this, bcmbal_buf *buf);
+
+/** Initializes a bcmbal_action struct. This sets all fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_action_set_default(bcmbal_action *this);
+
+/** Packs a bcmbal_action to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_action_pack(const bcmbal_action *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_action would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_action_get_packed_length(const bcmbal_action *this);
+
+/** Unpacks a bcmbal_action from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_action_unpack(bcmbal_action *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_action struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_action_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_action is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_action_bounds_check(const bcmbal_action *this);
+
+/** Initializes a bcmbal_aggregation_port_id_list_u8 struct. This sets all
+ * fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_aggregation_port_id_list_u8_set_default(bcmbal_aggregation_port_id_list_u8 *this);
+
+/** Packs a bcmbal_aggregation_port_id_list_u8 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_aggregation_port_id_list_u8_pack(const bcmbal_aggregation_port_id_list_u8 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_aggregation_port_id_list_u8 would
+ * occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_aggregation_port_id_list_u8_get_packed_length(const bcmbal_aggregation_port_id_list_u8 *this);
+
+/** Unpacks a bcmbal_aggregation_port_id_list_u8 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_aggregation_port_id_list_u8_unpack(bcmbal_aggregation_port_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_aggregation_port_id_list_u8 struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_aggregation_port_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_aggregation_port_id_list_u8 is out of
+ * bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_aggregation_port_id_list_u8_bounds_check(const bcmbal_aggregation_port_id_list_u8 *this);
+
+/** Initializes a bcmbal_classifier struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_classifier_set_default(bcmbal_classifier *this);
+
+/** Packs a bcmbal_classifier to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_classifier_pack(const bcmbal_classifier *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_classifier would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_classifier_get_packed_length(const bcmbal_classifier *this);
+
+/** Unpacks a bcmbal_classifier from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_classifier_unpack(bcmbal_classifier *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_classifier struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_classifier_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_classifier is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_classifier_bounds_check(const bcmbal_classifier *this);
+
+/** Initializes a bcmbal_dest struct. This sets all fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_dest_set_default(bcmbal_dest *this);
+
+/** Packs a bcmbal_dest to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_dest_pack(const bcmbal_dest *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_dest would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_dest_get_packed_length(const bcmbal_dest *this);
+
+/** Unpacks a bcmbal_dest from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_dest_unpack(bcmbal_dest *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_dest struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_dest_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_dest is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_dest_bounds_check(const bcmbal_dest *this);
+
+/** Initializes a bcmbal_flow_id_list_u32 struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_flow_id_list_u32_set_default(bcmbal_flow_id_list_u32 *this);
+
+/** Packs a bcmbal_flow_id_list_u32 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_id_list_u32_pack(const bcmbal_flow_id_list_u32 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_flow_id_list_u32 would occupy on the
+ * wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_flow_id_list_u32_get_packed_length(const bcmbal_flow_id_list_u32 *this);
+
+/** Unpacks a bcmbal_flow_id_list_u32 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_id_list_u32_unpack(bcmbal_flow_id_list_u32 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_flow_id_list_u32 struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_flow_id_list_u32_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_flow_id_list_u32 is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_id_list_u32_bounds_check(const bcmbal_flow_id_list_u32 *this);
+
+/** Initializes a bcmbal_tm_queue_ref struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_queue_ref_set_default(bcmbal_tm_queue_ref *this);
+
+/** Packs a bcmbal_tm_queue_ref to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_ref_pack(const bcmbal_tm_queue_ref *this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_queue_ref from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_ref_unpack(bcmbal_tm_queue_ref *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_queue_ref struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_queue_ref_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_queue_ref is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_ref_bounds_check(const bcmbal_tm_queue_ref *this);
+
+/** Initializes a bcmbal_group_member_info struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_group_member_info_set_default(bcmbal_group_member_info *this);
+
+/** Packs a bcmbal_group_member_info to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_member_info_pack(const bcmbal_group_member_info *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_group_member_info would occupy on the
+ * wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_group_member_info_get_packed_length(const bcmbal_group_member_info *this);
+
+/** Unpacks a bcmbal_group_member_info from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_member_info_unpack(bcmbal_group_member_info *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_group_member_info struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_group_member_info_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_group_member_info is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_member_info_bounds_check(const bcmbal_group_member_info *this);
+
+/** Initializes a bcmbal_group_member_info_list_u16 struct. This sets all
+ * fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_group_member_info_list_u16_set_default(bcmbal_group_member_info_list_u16 *this);
+
+/** Packs a bcmbal_group_member_info_list_u16 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_member_info_list_u16_pack(const bcmbal_group_member_info_list_u16 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_group_member_info_list_u16 would
+ * occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_group_member_info_list_u16_get_packed_length(const bcmbal_group_member_info_list_u16 *this);
+
+/** Unpacks a bcmbal_group_member_info_list_u16 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_member_info_list_u16_unpack(bcmbal_group_member_info_list_u16 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_group_member_info_list_u16 struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_group_member_info_list_u16_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_group_member_info_list_u16 is out of
+ * bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_member_info_list_u16_bounds_check(const bcmbal_group_member_info_list_u16 *this);
+
+/** Initializes a bcmbal_password struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_password_set_default(bcmbal_password *this);
+
+/** Packs a bcmbal_password to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_password_pack(const bcmbal_password *this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_password from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_password_unpack(bcmbal_password *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_password struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_password_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_password is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_password_bounds_check(const bcmbal_password *this);
+
+/** Initializes a bcmbal_registration_id struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_registration_id_set_default(bcmbal_registration_id *this);
+
+/** Packs a bcmbal_registration_id to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_registration_id_pack(const bcmbal_registration_id *this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_registration_id from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_registration_id_unpack(bcmbal_registration_id *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_registration_id struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_registration_id_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_registration_id is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_registration_id_bounds_check(const bcmbal_registration_id *this);
+
+/** Initializes a bcmbal_serial_number struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_serial_number_set_default(bcmbal_serial_number *this);
+
+/** Packs a bcmbal_serial_number to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_serial_number_pack(const bcmbal_serial_number *this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_serial_number from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_serial_number_unpack(bcmbal_serial_number *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_serial_number struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_serial_number_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_serial_number is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_serial_number_bounds_check(const bcmbal_serial_number *this);
+
+/** Initializes a bcmbal_service_port_id_list_u8 struct. This sets all fields
+ * to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_service_port_id_list_u8_set_default(bcmbal_service_port_id_list_u8 *this);
+
+/** Packs a bcmbal_service_port_id_list_u8 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_service_port_id_list_u8_pack(const bcmbal_service_port_id_list_u8 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_service_port_id_list_u8 would occupy
+ * on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_service_port_id_list_u8_get_packed_length(const bcmbal_service_port_id_list_u8 *this);
+
+/** Unpacks a bcmbal_service_port_id_list_u8 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_service_port_id_list_u8_unpack(bcmbal_service_port_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_service_port_id_list_u8 struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_service_port_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_service_port_id_list_u8 is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_service_port_id_list_u8_bounds_check(const bcmbal_service_port_id_list_u8 *this);
+
+/** Initializes a bcmbal_sla struct. This sets all fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_sla_set_default(bcmbal_sla *this);
+
+/** Packs a bcmbal_sla to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_sla_pack(const bcmbal_sla *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_sla would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_sla_get_packed_length(const bcmbal_sla *this);
+
+/** Unpacks a bcmbal_sla from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_sla_unpack(bcmbal_sla *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_sla struct and collects memory requirements above
+ * and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_sla_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_sla is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_sla_bounds_check(const bcmbal_sla *this);
+
+/** Initializes a bcmbal_sub_id_list_u16 struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_sub_id_list_u16_set_default(bcmbal_sub_id_list_u16 *this);
+
+/** Packs a bcmbal_sub_id_list_u16 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_sub_id_list_u16_pack(const bcmbal_sub_id_list_u16 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_sub_id_list_u16 would occupy on the
+ * wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_sub_id_list_u16_get_packed_length(const bcmbal_sub_id_list_u16 *this);
+
+/** Unpacks a bcmbal_sub_id_list_u16 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_sub_id_list_u16_unpack(bcmbal_sub_id_list_u16 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_sub_id_list_u16 struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_sub_id_list_u16_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_sub_id_list_u16 is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_sub_id_list_u16_bounds_check(const bcmbal_sub_id_list_u16 *this);
+
+/** Initializes a bcmbal_tm_red struct. This sets all fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_red_set_default(bcmbal_tm_red *this);
+
+/** Packs a bcmbal_tm_red to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_red_pack(const bcmbal_tm_red *this, bcmbal_buf *buf);
+
+/** Unpacks a bcmbal_tm_red from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_red_unpack(bcmbal_tm_red *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_red struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_red_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_red is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_red_bounds_check(const bcmbal_tm_red *this);
+
+/** Initializes a bcmbal_tm_bac struct. This sets all fields to default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_bac_set_default(bcmbal_tm_bac *this);
+
+/** Packs a bcmbal_tm_bac to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_bac_pack(const bcmbal_tm_bac *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_bac would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_bac_get_packed_length(const bcmbal_tm_bac *this);
+
+/** Unpacks a bcmbal_tm_bac from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_bac_unpack(bcmbal_tm_bac *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_bac struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_bac_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_bac is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_bac_bounds_check(const bcmbal_tm_bac *this);
+
+/** Initializes a bcmbal_tm_queue_id_list_u8 struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_queue_id_list_u8_set_default(bcmbal_tm_queue_id_list_u8 *this);
+
+/** Packs a bcmbal_tm_queue_id_list_u8 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_id_list_u8_pack(const bcmbal_tm_queue_id_list_u8 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_queue_id_list_u8 would occupy on
+ * the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_queue_id_list_u8_get_packed_length(const bcmbal_tm_queue_id_list_u8 *this);
+
+/** Unpacks a bcmbal_tm_queue_id_list_u8 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_id_list_u8_unpack(bcmbal_tm_queue_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_queue_id_list_u8 struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_queue_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_queue_id_list_u8 is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_id_list_u8_bounds_check(const bcmbal_tm_queue_id_list_u8 *this);
+
+/** Initializes a bcmbal_tm_sched_id_list_u8 struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_sched_id_list_u8_set_default(bcmbal_tm_sched_id_list_u8 *this);
+
+/** Packs a bcmbal_tm_sched_id_list_u8 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_id_list_u8_pack(const bcmbal_tm_sched_id_list_u8 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_sched_id_list_u8 would occupy on
+ * the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_sched_id_list_u8_get_packed_length(const bcmbal_tm_sched_id_list_u8 *this);
+
+/** Unpacks a bcmbal_tm_sched_id_list_u8 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_id_list_u8_unpack(bcmbal_tm_sched_id_list_u8 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_sched_id_list_u8 struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_sched_id_list_u8_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_sched_id_list_u8 is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_id_list_u8_bounds_check(const bcmbal_tm_sched_id_list_u8 *this);
+
+/** Initializes a bcmbal_tm_sched_owner struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_sched_owner_set_default(bcmbal_tm_sched_owner *this);
+
+/** Packs a bcmbal_tm_sched_owner to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_owner_pack(const bcmbal_tm_sched_owner *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_sched_owner would occupy on the
+ * wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_sched_owner_get_packed_length(const bcmbal_tm_sched_owner *this);
+
+/** Unpacks a bcmbal_tm_sched_owner from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_owner_unpack(bcmbal_tm_sched_owner *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_sched_owner struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_sched_owner_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_sched_owner is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_owner_bounds_check(const bcmbal_tm_sched_owner *this);
+
+/** Initializes a bcmbal_tm_sched_parent struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_sched_parent_set_default(bcmbal_tm_sched_parent *this);
+
+/** Packs a bcmbal_tm_sched_parent to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_parent_pack(const bcmbal_tm_sched_parent *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_sched_parent would occupy on the
+ * wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_sched_parent_get_packed_length(const bcmbal_tm_sched_parent *this);
+
+/** Unpacks a bcmbal_tm_sched_parent from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_parent_unpack(bcmbal_tm_sched_parent *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_sched_parent struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_sched_parent_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_sched_parent is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_parent_bounds_check(const bcmbal_tm_sched_parent *this);
+
+/** Initializes a bcmbal_tm_shaping struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_shaping_set_default(bcmbal_tm_shaping *this);
+
+/** Packs a bcmbal_tm_shaping to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_shaping_pack(const bcmbal_tm_shaping *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_shaping would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_shaping_get_packed_length(const bcmbal_tm_shaping *this);
+
+/** Unpacks a bcmbal_tm_shaping from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_shaping_unpack(bcmbal_tm_shaping *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_shaping struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_shaping_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_shaping is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_shaping_bounds_check(const bcmbal_tm_shaping *this);
+
+/** Initializes a bcmbal_tm_tcont_sla struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_tm_tcont_sla_set_default(bcmbal_tm_tcont_sla *this);
+
+/** Packs a bcmbal_tm_tcont_sla to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_tcont_sla_pack(const bcmbal_tm_tcont_sla *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_tm_tcont_sla would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_tcont_sla_get_packed_length(const bcmbal_tm_tcont_sla *this);
+
+/** Unpacks a bcmbal_tm_tcont_sla from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_tcont_sla_unpack(bcmbal_tm_tcont_sla *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_tm_tcont_sla struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_tcont_sla_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_tm_tcont_sla is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_tcont_sla_bounds_check(const bcmbal_tm_tcont_sla *this);
+
+/** Initializes a bcmbal_u8_list_u32 struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ */
+void bcmbal_u8_list_u32_set_default(bcmbal_u8_list_u32 *this);
+
+/** Packs a bcmbal_u8_list_u32 to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_u8_list_u32_pack(const bcmbal_u8_list_u32 *this, bcmbal_buf *buf);
+
+/** Gets the number of bytes that a bcmbal_u8_list_u32 would occupy on the wire
+ *
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_u8_list_u32_get_packed_length(const bcmbal_u8_list_u32 *this);
+
+/** Unpacks a bcmbal_u8_list_u32 from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_u8_list_u32_unpack(bcmbal_u8_list_u32 *this, bcmbal_buf *buf, void **extra_mem);
+
+/** Scans past a packed bcmbal_u8_list_u32 struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_u8_list_u32_scan(bcmbal_buf *packed, uint32_t *extra_mem);
+
+/** Checks if any field in the bcmbal_u8_list_u32 is out of bounds
+ *
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_u8_list_u32_bounds_check(const bcmbal_u8_list_u32 *this);
+
+/** Initializes a bcmbal_access_terminal_key struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_access_terminal_key_set_default(bcmbal_access_terminal_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_access_terminal_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_key_pack(const bcmbal_access_terminal_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_access_terminal_key would occupy on
+ * the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_access_terminal_key_get_packed_length(const bcmbal_access_terminal_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_access_terminal_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_key_unpack(bcmbal_access_terminal_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_access_terminal_key struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_access_terminal_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_access_terminal_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_key_bounds_check(const bcmbal_access_terminal_key *this, bcmbal_presence_mask fields_present, bcmbal_access_terminal_key_id *failed_prop);
+
+/** Initializes a bcmbal_access_terminal_cfg_data struct. This sets all fields
+ * to default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_access_terminal_cfg_data_set_default(bcmbal_access_terminal_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_access_terminal_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_cfg_data_pack(const bcmbal_access_terminal_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_access_terminal_cfg_data would occupy
+ * on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_access_terminal_cfg_data_get_packed_length(const bcmbal_access_terminal_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_access_terminal_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_cfg_data_unpack(bcmbal_access_terminal_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_access_terminal_cfg_data struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_access_terminal_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_access_terminal_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_cfg_data_bounds_check(const bcmbal_access_terminal_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_access_terminal_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_access_terminal_ind_data struct. This sets all fields
+ * to default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_access_terminal_ind_data_set_default(bcmbal_access_terminal_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_access_terminal_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_ind_data_pack(const bcmbal_access_terminal_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_access_terminal_ind_data would occupy
+ * on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_access_terminal_ind_data_get_packed_length(const bcmbal_access_terminal_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_access_terminal_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_ind_data_unpack(bcmbal_access_terminal_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_access_terminal_ind_data struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_access_terminal_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_access_terminal_ind_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_access_terminal_ind_data_bounds_check(const bcmbal_access_terminal_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_access_terminal_ind_id *failed_prop);
+
+/** Initializes a bcmbal_flow_key struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_flow_key_set_default(bcmbal_flow_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_flow_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_key_pack(const bcmbal_flow_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_flow_key would occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_flow_key_get_packed_length(const bcmbal_flow_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_flow_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_key_unpack(bcmbal_flow_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_flow_key struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_flow_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_flow_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_key_bounds_check(const bcmbal_flow_key *this, bcmbal_presence_mask fields_present, bcmbal_flow_key_id *failed_prop);
+
+/** Initializes a bcmbal_flow_cfg_data struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_flow_cfg_data_set_default(bcmbal_flow_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_flow_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_cfg_data_pack(const bcmbal_flow_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_flow_cfg_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_flow_cfg_data_get_packed_length(const bcmbal_flow_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_flow_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_cfg_data_unpack(bcmbal_flow_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_flow_cfg_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_flow_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_flow_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_cfg_data_bounds_check(const bcmbal_flow_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_flow_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_flow_stat_data struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_flow_stat_data_set_default(bcmbal_flow_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_flow_stat_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_stat_data_pack(const bcmbal_flow_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_flow_stat_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_flow_stat_data_get_packed_length(const bcmbal_flow_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_flow_stat_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_stat_data_unpack(bcmbal_flow_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_flow_stat_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_flow_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_flow_stat_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_stat_data_bounds_check(const bcmbal_flow_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_flow_stat_id *failed_prop);
+
+/** Initializes a bcmbal_flow_ind_data struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_flow_ind_data_set_default(bcmbal_flow_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_flow_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_ind_data_pack(const bcmbal_flow_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_flow_ind_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_flow_ind_data_get_packed_length(const bcmbal_flow_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_flow_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_ind_data_unpack(bcmbal_flow_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_flow_ind_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_flow_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_flow_ind_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_flow_ind_data_bounds_check(const bcmbal_flow_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_flow_ind_id *failed_prop);
+
+/** Initializes a bcmbal_group_key struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_group_key_set_default(bcmbal_group_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_group_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_key_pack(const bcmbal_group_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_group_key would occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_group_key_get_packed_length(const bcmbal_group_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_group_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_key_unpack(bcmbal_group_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_group_key struct and collects memory requirements
+ * above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_group_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_group_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_key_bounds_check(const bcmbal_group_key *this, bcmbal_presence_mask fields_present, bcmbal_group_key_id *failed_prop);
+
+/** Initializes a bcmbal_group_cfg_data struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_group_cfg_data_set_default(bcmbal_group_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_group_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_cfg_data_pack(const bcmbal_group_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_group_cfg_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_group_cfg_data_get_packed_length(const bcmbal_group_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_group_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_cfg_data_unpack(bcmbal_group_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_group_cfg_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_group_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_group_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_group_cfg_data_bounds_check(const bcmbal_group_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_group_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_interface_key struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_interface_key_set_default(bcmbal_interface_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_interface_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_key_pack(const bcmbal_interface_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_interface_key would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_interface_key_get_packed_length(const bcmbal_interface_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_interface_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_key_unpack(bcmbal_interface_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_interface_key struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_interface_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_interface_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_key_bounds_check(const bcmbal_interface_key *this, bcmbal_presence_mask fields_present, bcmbal_interface_key_id *failed_prop);
+
+/** Initializes a bcmbal_interface_cfg_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_interface_cfg_data_set_default(bcmbal_interface_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_interface_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_cfg_data_pack(const bcmbal_interface_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_interface_cfg_data would occupy on
+ * the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_interface_cfg_data_get_packed_length(const bcmbal_interface_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_interface_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_cfg_data_unpack(bcmbal_interface_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_interface_cfg_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_interface_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_interface_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_cfg_data_bounds_check(const bcmbal_interface_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_interface_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_interface_stat_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_interface_stat_data_set_default(bcmbal_interface_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_interface_stat_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_stat_data_pack(const bcmbal_interface_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_interface_stat_data would occupy on
+ * the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_interface_stat_data_get_packed_length(const bcmbal_interface_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_interface_stat_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_stat_data_unpack(bcmbal_interface_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_interface_stat_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_interface_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_interface_stat_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_stat_data_bounds_check(const bcmbal_interface_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_interface_stat_id *failed_prop);
+
+/** Initializes a bcmbal_interface_ind_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_interface_ind_data_set_default(bcmbal_interface_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_interface_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_ind_data_pack(const bcmbal_interface_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_interface_ind_data would occupy on
+ * the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_interface_ind_data_get_packed_length(const bcmbal_interface_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_interface_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_ind_data_unpack(bcmbal_interface_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_interface_ind_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_interface_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_interface_ind_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_interface_ind_data_bounds_check(const bcmbal_interface_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_interface_ind_id *failed_prop);
+
+/** Initializes a bcmbal_packet_key struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_packet_key_set_default(bcmbal_packet_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_packet_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_key_pack(const bcmbal_packet_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_packet_key would occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_packet_key_get_packed_length(const bcmbal_packet_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_packet_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_key_unpack(bcmbal_packet_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_packet_key struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_packet_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_packet_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_key_bounds_check(const bcmbal_packet_key *this, bcmbal_presence_mask fields_present, bcmbal_packet_key_id *failed_prop);
+
+/** Initializes a bcmbal_packet_cfg_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_packet_cfg_data_set_default(bcmbal_packet_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_packet_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_cfg_data_pack(const bcmbal_packet_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_packet_cfg_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_packet_cfg_data_get_packed_length(const bcmbal_packet_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_packet_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_cfg_data_unpack(bcmbal_packet_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_packet_cfg_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_packet_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_packet_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_cfg_data_bounds_check(const bcmbal_packet_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_packet_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_packet_ind_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_packet_ind_data_set_default(bcmbal_packet_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_packet_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_ind_data_pack(const bcmbal_packet_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_packet_ind_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_packet_ind_data_get_packed_length(const bcmbal_packet_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_packet_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_ind_data_unpack(bcmbal_packet_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_packet_ind_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_packet_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_packet_ind_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_packet_ind_data_bounds_check(const bcmbal_packet_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_packet_ind_id *failed_prop);
+
+/** Initializes a bcmbal_subscriber_terminal_key struct. This sets all fields
+ * to default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_subscriber_terminal_key_set_default(bcmbal_subscriber_terminal_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_subscriber_terminal_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_key_pack(const bcmbal_subscriber_terminal_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_subscriber_terminal_key would occupy
+ * on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_subscriber_terminal_key_get_packed_length(const bcmbal_subscriber_terminal_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_subscriber_terminal_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_key_unpack(bcmbal_subscriber_terminal_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_subscriber_terminal_key struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_subscriber_terminal_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_subscriber_terminal_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_key_bounds_check(const bcmbal_subscriber_terminal_key *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_key_id *failed_prop);
+
+/** Initializes a bcmbal_subscriber_terminal_cfg_data struct. This sets all
+ * fields to default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_subscriber_terminal_cfg_data_set_default(bcmbal_subscriber_terminal_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_subscriber_terminal_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_pack(const bcmbal_subscriber_terminal_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_subscriber_terminal_cfg_data would
+ * occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_subscriber_terminal_cfg_data_get_packed_length(const bcmbal_subscriber_terminal_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_subscriber_terminal_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_unpack(bcmbal_subscriber_terminal_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_subscriber_terminal_cfg_data struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_subscriber_terminal_cfg_data is out of
+ * bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_cfg_data_bounds_check(const bcmbal_subscriber_terminal_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_subscriber_terminal_stat_data struct. This sets all
+ * fields to default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_subscriber_terminal_stat_data_set_default(bcmbal_subscriber_terminal_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_subscriber_terminal_stat_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_stat_data_pack(const bcmbal_subscriber_terminal_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_subscriber_terminal_stat_data would
+ * occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_subscriber_terminal_stat_data_get_packed_length(const bcmbal_subscriber_terminal_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_subscriber_terminal_stat_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_stat_data_unpack(bcmbal_subscriber_terminal_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_subscriber_terminal_stat_data struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_subscriber_terminal_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_subscriber_terminal_stat_data is out of
+ * bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_stat_data_bounds_check(const bcmbal_subscriber_terminal_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_stat_id *failed_prop);
+
+/** Initializes a bcmbal_subscriber_terminal_ind_data struct. This sets all
+ * fields to default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_subscriber_terminal_ind_data_set_default(bcmbal_subscriber_terminal_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_subscriber_terminal_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_ind_data_pack(const bcmbal_subscriber_terminal_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_subscriber_terminal_ind_data would
+ * occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_subscriber_terminal_ind_data_get_packed_length(const bcmbal_subscriber_terminal_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_subscriber_terminal_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_ind_data_unpack(bcmbal_subscriber_terminal_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_subscriber_terminal_ind_data struct and collects
+ * memory requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_subscriber_terminal_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_subscriber_terminal_ind_data is out of
+ * bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_subscriber_terminal_ind_data_bounds_check(const bcmbal_subscriber_terminal_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_subscriber_terminal_ind_id *failed_prop);
+
+/** Initializes a bcmbal_tm_queue_key struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_queue_key_set_default(bcmbal_tm_queue_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_queue_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_key_pack(const bcmbal_tm_queue_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_queue_key would occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_queue_key_get_packed_length(const bcmbal_tm_queue_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_queue_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_key_unpack(bcmbal_tm_queue_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_queue_key struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_queue_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_queue_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_key_bounds_check(const bcmbal_tm_queue_key *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_key_id *failed_prop);
+
+/** Initializes a bcmbal_tm_queue_cfg_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_queue_cfg_data_set_default(bcmbal_tm_queue_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_queue_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_cfg_data_pack(const bcmbal_tm_queue_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_queue_cfg_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_queue_cfg_data_get_packed_length(const bcmbal_tm_queue_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_queue_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_cfg_data_unpack(bcmbal_tm_queue_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_queue_cfg_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_queue_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_queue_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_cfg_data_bounds_check(const bcmbal_tm_queue_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_tm_queue_stat_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_queue_stat_data_set_default(bcmbal_tm_queue_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_queue_stat_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_stat_data_pack(const bcmbal_tm_queue_stat_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_queue_stat_data would occupy on
+ * the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_queue_stat_data_get_packed_length(const bcmbal_tm_queue_stat_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_queue_stat_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_stat_data_unpack(bcmbal_tm_queue_stat_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_queue_stat_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_queue_stat_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_queue_stat_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_stat_data_bounds_check(const bcmbal_tm_queue_stat_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_stat_id *failed_prop);
+
+/** Initializes a bcmbal_tm_queue_ind_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_queue_ind_data_set_default(bcmbal_tm_queue_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_queue_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_ind_data_pack(const bcmbal_tm_queue_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_queue_ind_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_queue_ind_data_get_packed_length(const bcmbal_tm_queue_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_queue_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_ind_data_unpack(bcmbal_tm_queue_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_queue_ind_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_queue_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_queue_ind_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_queue_ind_data_bounds_check(const bcmbal_tm_queue_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_queue_ind_id *failed_prop);
+
+/** Initializes a bcmbal_tm_sched_key struct. This sets all fields to default
+ * values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_sched_key_set_default(bcmbal_tm_sched_key *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_sched_key to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_key_pack(const bcmbal_tm_sched_key *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_sched_key would occupy on the wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_sched_key_get_packed_length(const bcmbal_tm_sched_key *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_sched_key from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_key_unpack(bcmbal_tm_sched_key *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_sched_key struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_sched_key_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_sched_key is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_key_bounds_check(const bcmbal_tm_sched_key *this, bcmbal_presence_mask fields_present, bcmbal_tm_sched_key_id *failed_prop);
+
+/** Initializes a bcmbal_tm_sched_cfg_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_sched_cfg_data_set_default(bcmbal_tm_sched_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_sched_cfg_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_cfg_data_pack(const bcmbal_tm_sched_cfg_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_sched_cfg_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_sched_cfg_data_get_packed_length(const bcmbal_tm_sched_cfg_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_sched_cfg_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_cfg_data_unpack(bcmbal_tm_sched_cfg_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_sched_cfg_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_sched_cfg_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_sched_cfg_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_cfg_data_bounds_check(const bcmbal_tm_sched_cfg_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_sched_cfg_id *failed_prop);
+
+/** Initializes a bcmbal_tm_sched_ind_data struct. This sets all fields to
+ * default values.
+ *
+ * \param this Pointer to the structure
+ * \param fields_present Bitmask of which fields are present in the structure.
+ */
+void bcmbal_tm_sched_ind_data_set_default(bcmbal_tm_sched_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Packs a bcmbal_tm_sched_ind_data to bytes
+ *
+ * \param this Pointer to the object to pack
+ * \param buf Pointer to the buffer to write to
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the pack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_ind_data_pack(const bcmbal_tm_sched_ind_data *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+
+/** Gets the number of bytes that a bcmbal_tm_sched_ind_data would occupy on the
+ * wire
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return The structure size in bytes
+ */
+uint32_t bcmbal_tm_sched_ind_data_get_packed_length(const bcmbal_tm_sched_ind_data *this, bcmbal_presence_mask fields_present);
+
+/** Unpacks a bcmbal_tm_sched_ind_data from bytes
+ *
+ * \param this Pointer to the object to unpack
+ * \param buf Pointer to the buffer to read from
+ * \param extra_mem Pointer to the first location in memory to use to store
+ * pointer fields that are NULL. Setting this to NULL will cause an error when
+ * a NULL pointer is encountered.
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE if the unpack was successful, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_ind_data_unpack(bcmbal_tm_sched_ind_data *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+
+/** Scans past a packed bcmbal_tm_sched_ind_data struct and collects memory
+ * requirements above and beyond sizeof()
+ *
+ * \param packed A stream pointing to the packed byte stream
+ * \param extra_mem Number of additional storage bytes required
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \return TRUE on success, FALSE on failure
+ */
+bcmos_bool bcmbal_tm_sched_ind_data_scan(bcmbal_buf *packed, uint32_t *extra_mem, bcmbal_presence_mask fields_present);
+
+/** Checks if any field in the bcmbal_tm_sched_ind_data is out of bounds
+ *
+ * \param fields_present Bitmask of which fields are present in the structure.
+ * \param failed_prop Reference to the property that was out of range (only set
+ * on failure)
+ * \return TRUE if all fields are in the correct range, FALSE otherwise
+ */
+bcmos_bool bcmbal_tm_sched_ind_data_bounds_check(const bcmbal_tm_sched_ind_data *this, bcmbal_presence_mask fields_present, bcmbal_tm_sched_ind_id *failed_prop);
+#endif /* BAL_MODEL_FUNCS */
diff --git a/bal_release/src/lib/libobjmsg/bal_msg.c b/bal_release/src/lib/libobjmsg/bal_msg.c
new file mode 100644
index 0000000..285be80
--- /dev/null
+++ b/bal_release/src/lib/libobjmsg/bal_msg.c
@@ -0,0 +1,220 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_msg.c
+ * @brief BAL message helper functions
+ * @addtogroup ctrlr
+ */
+#include <bal_msg.h>
+#include <bal_obj_msg_pack_unpack.h>
+
+/*
+ * Clone BAL message
+ * Returns payload_ptr of the clone
+ */
+void *bcmbal_msg_clone(void *bal_obj)
+{
+ bal_comm_msg_hdr *msg_hdr = bcmbal_bal_hdr_get(bal_obj);
+ bal_comm_msg_hdr *clone_hdr = NULL;
+ bcmos_errno err = bcmbal_obj_msg_clone(&clone_hdr, msg_hdr);
+ return ((int)err >= 0) ? bcmbal_payload_ptr_get(clone_hdr) : NULL;
+}
+
+/*
+ * Send a BAL message given the payload pointer
+ */
+bcmos_errno bcmbal_msg_send(bcmos_msg_queue *queue, void *msg_payload, bcmos_msg_send_flags flags)
+{
+ bcmos_msg *packed_msg = NULL;
+ bcmos_errno err;
+
+ /* pack and send */
+ err = bcmbal_obj_msg_pack(bcmbal_bal_hdr_get(msg_payload), &packed_msg);
+ if (err != BCM_ERR_OK)
+ return err;
+
+ err = bcmos_msg_send(queue, packed_msg, flags);
+
+ if ((flags & BCMOS_MSG_SEND_NO_FREE_ON_ERROR) == 0)
+ {
+ /* Release the original message */
+ bcmbal_msg_free(msg_payload);
+ }
+ else if (err != BCM_ERR_OK)
+ {
+ /* bcmos_msg_send() failed, but packed_msg wasn't released because of the flag. */
+ bcmos_msg_free(packed_msg);
+ }
+
+ return err;
+}
+
+/*
+ * Call callback in the context of the target module and pass it the BAL message pointer
+ */
+bcmos_errno bcmbal_msg_call(void *msg_payload,
+ bcmos_module_id module, F_bcmos_msg_handler cb, bcmos_msg_send_flags flags)
+{
+ bcmos_msg *m = bcmbal_bcmos_hdr_get(msg_payload);
+ m->handler = cb;
+ return bcmos_msg_send_to_module(module, m, flags);
+}
+
+bcmos_errno bcmbal_msg_recv(bcmos_msg_queue *queue, uint32_t timeout, void **msg_payload)
+{
+ bcmos_errno ret;
+ bcmos_msg *msg;
+ bal_comm_msg_hdr *unpacked_msg = (*msg_payload) ? bcmbal_bal_hdr_get(*msg_payload) : NULL;
+
+ do {
+ ret = bcmos_msg_recv(queue, timeout, &msg);
+ if(BCM_ERR_OK != ret)
+ {
+ bcmos_printf("%s: error during bcmos_msg_recv (error:%s)\n",
+ __FUNCTION__,
+ bcmos_strerror(ret));
+ break;
+ }
+
+ /* Got a message. Now unpack it */
+ ret = bcmbal_obj_msg_unpack(msg, &unpacked_msg);
+ bcmos_msg_free(msg); /* release packed message. It is no longer needed */
+ if (BCM_ERR_OK != ret)
+ {
+ bcmos_printf("%s: bcmbal_obj_msg_unpack (error:%s)\n",
+ __FUNCTION__, bcmos_strerror(ret));
+ break;
+ }
+
+ /* If message was allocated in unpack - assign it */
+ if (! *msg_payload)
+ *msg_payload = bcmbal_payload_ptr_get(unpacked_msg);
+
+ } while (0);
+
+ return ret;
+}
+
+int32_t bcmbal_bal_msg_hdr_get_packed_length(void)
+{
+ return 21; /* See bcmbal_bal_msg_hdr_pack() */
+}
+
+static int32_t bcmbal_bal_msg_hdr_get_ex_id_offset(void)
+{
+ return 16; /* See bcmbal_bal_msg_hdr_pack() */
+}
+
+/** Pack a BAL message header to a byte stream */
+bcmos_errno bcmbal_bal_msg_hdr_pack(const bal_comm_msg_hdr *msg, bcmbal_buf *buf)
+{
+ bcmos_bool ret;
+
+ /* bcmos_msg header pack... (8 bytes post-pack) */
+ ret = bcmbal_buf_write_u32(buf, buf->len);
+
+ ret = ret && bcmbal_buf_write_u16(buf, (uint16_t)msg->m.type);
+ ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->m.instance);
+ ret = ret && bcmbal_buf_write_u8(buf, (uint8_t)msg->m.sender);
+
+ /* ...and then the rest of the header (15 bytes post-pack) */
+ ret = ret && bcmbal_buf_write_u8(buf, msg->version_major);
+ ret = ret && bcmbal_buf_write_u8(buf, msg->version_minor);
+ ret = ret && bcmbal_buf_write_u32(buf, msg->msg_id); /* the msg_id cannot be compressed */
+ ret = ret && bcmbal_buf_write_u16(buf, (uint16_t)msg->msg_type);
+ ret = ret && bcmbal_buf_write_u32(buf, msg->ex_id);
+ ret = ret && bcmbal_buf_write_u8(buf, msg->sender);
+
+ return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
+}
+
+/** Unpack a BAL message header from a byte stream */
+bcmos_errno bcmbal_bal_msg_hdr_unpack(bal_comm_msg_hdr *msg, bcmbal_buf *buf)
+{
+ uint16_t m_type;
+ uint8_t m_instance;
+ uint8_t m_sender;
+ uint32_t m_size;
+
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint32_t msg_id;
+ uint16_t msg_type;
+ uint32_t ex_id;
+ uint8_t sender;
+
+ bcmos_bool ret;
+
+ ret = bcmbal_buf_read_u32(buf, &m_size);
+ ret = ret && bcmbal_buf_read_u16(buf, &m_type);
+ ret = ret && bcmbal_buf_read_u8(buf, &m_instance);
+ ret = ret && bcmbal_buf_read_u8(buf, &m_sender);
+
+ ret = ret && bcmbal_buf_read_u8(buf, &version_major);
+ ret = ret && bcmbal_buf_read_u8(buf, &version_minor);
+ ret = ret && bcmbal_buf_read_u32(buf, &msg_id);
+ ret = ret && bcmbal_buf_read_u16(buf, &msg_type);
+ ret = ret && bcmbal_buf_read_u32(buf, &ex_id);
+ ret = ret && bcmbal_buf_read_u8(buf, &sender);
+
+ if (ret)
+ {
+ msg->m.type = (bcmos_msg_id)m_type;
+ msg->m.instance = (bcmos_msg_instance)m_instance;
+ msg->m.sender = (bcmos_module_id)m_sender;
+ msg->m.size = m_size;
+
+ msg->version_major = version_major;
+ msg->version_minor = version_minor;
+ msg->msg_id = msg_id;
+ msg->msg_type = msg_type;
+ msg->ex_id = ex_id;
+ msg->sender = sender;
+ }
+
+ return ret ? BCM_ERR_OK : BCM_ERR_OVERFLOW;
+}
+
+/** Peek exchange_id in the received message without unpacking */
+bcmos_errno bcmbal_bal_msg_peek_ex_id(bcmos_msg *msg, uint32_t *ex_id)
+{
+ bcmbal_buf buf;
+ if (msg->size < bcmbal_bal_msg_hdr_get_packed_length())
+ return BCM_ERR_INTERNAL;
+ bcmbal_buf_init(&buf, msg->size, msg->data);
+ bcmolt_buf_set_pos(&buf, bcmbal_bal_msg_hdr_get_ex_id_offset());
+ bcmbal_buf_read_u32(&buf, ex_id);
+ return BCM_ERR_OK;
+}
+
+
+
diff --git a/bal_release/src/lib/libobjmsg/bal_obj_msg_pack_unpack.c b/bal_release/src/lib/libobjmsg/bal_obj_msg_pack_unpack.c
new file mode 100644
index 0000000..519af97
--- /dev/null
+++ b/bal_release/src/lib/libobjmsg/bal_obj_msg_pack_unpack.c
@@ -0,0 +1,558 @@
+#include <bcmos_system.h>
+#include <bal_msg.h>
+#include "bal_obj_msg_pack_unpack.h"
+
+typedef uint32_t (*bcmbal_func_packed_len) (void *this, bcmbal_presence_mask fields_present);
+typedef bcmos_bool (*bcmbal_func_pack) (void *this, bcmbal_buf *buf, bcmbal_presence_mask fields_present);
+typedef bcmos_bool (*bcmbal_func_unpack) (void *this, bcmbal_buf *buf, void **extra_mem, bcmbal_presence_mask fields_present);
+typedef bcmos_bool (*bcmbal_func_mem_scan) (bcmbal_buf * buf, uint32_t * extra_mem, bcmbal_presence_mask fields_present);
+
+/******************************************************************************/
+typedef struct bcmbal_group_info
+{
+ bcmbal_obj_id obj_type;
+ bcmbal_mgt_group group;
+ uint16_t subgroup;
+ uint32_t size;
+ uint32_t container_size; /* sizeof() the key/data container struct (0 for key groups) */
+ uint32_t data_offset; /* offsetof() data field within container struct (0 for key groups) */
+ bcmbal_func_packed_len get_packed_length;
+ bcmbal_func_pack pack;
+ bcmbal_func_unpack unpack;
+ bcmbal_func_mem_scan mem_scan;
+} bcmbal_group_info;
+
+/******************************************************************************/
+typedef struct bcmbal_group_ids
+{
+ uint32_t subgroup_count;
+ bcmbal_obj_group_id *subgroup_ids;
+} bcmbal_group_ids;
+
+/******************************************************************************/
+typedef struct bcmbal_instance_info
+{
+ int8_t offset;
+ int8_t size;
+} bcmbal_instance_info;
+
+/******************************************************************************/
+static bcmbal_group_info group_info_access_terminal_key = { BCMBAL_OBJ_ID_ACCESS_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_access_terminal_key), 0, 0, (bcmbal_func_packed_len) bcmbal_access_terminal_key_get_packed_length, (bcmbal_func_pack) bcmbal_access_terminal_key_pack, (bcmbal_func_unpack) bcmbal_access_terminal_key_unpack, bcmbal_access_terminal_key_scan };
+static bcmbal_group_info group_info_access_terminal_cfg = { BCMBAL_OBJ_ID_ACCESS_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_access_terminal_cfg_data), sizeof(bcmbal_access_terminal_cfg), offsetof(bcmbal_access_terminal_cfg, data), (bcmbal_func_packed_len) bcmbal_access_terminal_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_access_terminal_cfg_data_pack, (bcmbal_func_unpack) bcmbal_access_terminal_cfg_data_unpack, bcmbal_access_terminal_cfg_data_scan };
+static bcmbal_group_info group_info_access_terminal_ind = { BCMBAL_OBJ_ID_ACCESS_TERMINAL, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_access_terminal_ind_data), sizeof(bcmbal_access_terminal_ind), offsetof(bcmbal_access_terminal_ind, data), (bcmbal_func_packed_len) bcmbal_access_terminal_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_access_terminal_ind_data_pack, (bcmbal_func_unpack) bcmbal_access_terminal_ind_data_unpack, bcmbal_access_terminal_ind_data_scan };
+static bcmbal_group_info group_info_flow_key = { BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_flow_key), 0, 0, (bcmbal_func_packed_len) bcmbal_flow_key_get_packed_length, (bcmbal_func_pack) bcmbal_flow_key_pack, (bcmbal_func_unpack) bcmbal_flow_key_unpack, bcmbal_flow_key_scan };
+static bcmbal_group_info group_info_flow_cfg = { BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_flow_cfg_data), sizeof(bcmbal_flow_cfg), offsetof(bcmbal_flow_cfg, data), (bcmbal_func_packed_len) bcmbal_flow_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_flow_cfg_data_pack, (bcmbal_func_unpack) bcmbal_flow_cfg_data_unpack, bcmbal_flow_cfg_data_scan };
+static bcmbal_group_info group_info_flow_stat = { BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_STAT, 0, sizeof(bcmbal_flow_stat_data), sizeof(bcmbal_flow_stat), offsetof(bcmbal_flow_stat, data), (bcmbal_func_packed_len) bcmbal_flow_stat_data_get_packed_length, (bcmbal_func_pack) bcmbal_flow_stat_data_pack, (bcmbal_func_unpack) bcmbal_flow_stat_data_unpack, bcmbal_flow_stat_data_scan };
+static bcmbal_group_info group_info_flow_ind = { BCMBAL_OBJ_ID_FLOW, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_flow_ind_data), sizeof(bcmbal_flow_ind), offsetof(bcmbal_flow_ind, data), (bcmbal_func_packed_len) bcmbal_flow_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_flow_ind_data_pack, (bcmbal_func_unpack) bcmbal_flow_ind_data_unpack, bcmbal_flow_ind_data_scan };
+static bcmbal_group_info group_info_group_key = { BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_group_key), 0, 0, (bcmbal_func_packed_len) bcmbal_group_key_get_packed_length, (bcmbal_func_pack) bcmbal_group_key_pack, (bcmbal_func_unpack) bcmbal_group_key_unpack, bcmbal_group_key_scan };
+static bcmbal_group_info group_info_group_cfg = { BCMBAL_OBJ_ID_GROUP, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_group_cfg_data), sizeof(bcmbal_group_cfg), offsetof(bcmbal_group_cfg, data), (bcmbal_func_packed_len) bcmbal_group_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_group_cfg_data_pack, (bcmbal_func_unpack) bcmbal_group_cfg_data_unpack, bcmbal_group_cfg_data_scan };
+static bcmbal_group_info group_info_interface_key = { BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_interface_key), 0, 0, (bcmbal_func_packed_len) bcmbal_interface_key_get_packed_length, (bcmbal_func_pack) bcmbal_interface_key_pack, (bcmbal_func_unpack) bcmbal_interface_key_unpack, bcmbal_interface_key_scan };
+static bcmbal_group_info group_info_interface_cfg = { BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_interface_cfg_data), sizeof(bcmbal_interface_cfg), offsetof(bcmbal_interface_cfg, data), (bcmbal_func_packed_len) bcmbal_interface_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_interface_cfg_data_pack, (bcmbal_func_unpack) bcmbal_interface_cfg_data_unpack, bcmbal_interface_cfg_data_scan };
+static bcmbal_group_info group_info_interface_stat = { BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_STAT, 0, sizeof(bcmbal_interface_stat_data), sizeof(bcmbal_interface_stat), offsetof(bcmbal_interface_stat, data), (bcmbal_func_packed_len) bcmbal_interface_stat_data_get_packed_length, (bcmbal_func_pack) bcmbal_interface_stat_data_pack, (bcmbal_func_unpack) bcmbal_interface_stat_data_unpack, bcmbal_interface_stat_data_scan };
+static bcmbal_group_info group_info_interface_ind = { BCMBAL_OBJ_ID_INTERFACE, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_interface_ind_data), sizeof(bcmbal_interface_ind), offsetof(bcmbal_interface_ind, data), (bcmbal_func_packed_len) bcmbal_interface_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_interface_ind_data_pack, (bcmbal_func_unpack) bcmbal_interface_ind_data_unpack, bcmbal_interface_ind_data_scan };
+static bcmbal_group_info group_info_packet_key = { BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_packet_key), 0, 0, (bcmbal_func_packed_len) bcmbal_packet_key_get_packed_length, (bcmbal_func_pack) bcmbal_packet_key_pack, (bcmbal_func_unpack) bcmbal_packet_key_unpack, bcmbal_packet_key_scan };
+static bcmbal_group_info group_info_packet_cfg = { BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_packet_cfg_data), sizeof(bcmbal_packet_cfg), offsetof(bcmbal_packet_cfg, data), (bcmbal_func_packed_len) bcmbal_packet_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_packet_cfg_data_pack, (bcmbal_func_unpack) bcmbal_packet_cfg_data_unpack, bcmbal_packet_cfg_data_scan };
+static bcmbal_group_info group_info_packet_ind = { BCMBAL_OBJ_ID_PACKET, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_packet_ind_data), sizeof(bcmbal_packet_ind), offsetof(bcmbal_packet_ind, data), (bcmbal_func_packed_len) bcmbal_packet_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_packet_ind_data_pack, (bcmbal_func_unpack) bcmbal_packet_ind_data_unpack, bcmbal_packet_ind_data_scan };
+static bcmbal_group_info group_info_subscriber_terminal_key = { BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_subscriber_terminal_key), 0, 0, (bcmbal_func_packed_len) bcmbal_subscriber_terminal_key_get_packed_length, (bcmbal_func_pack) bcmbal_subscriber_terminal_key_pack, (bcmbal_func_unpack) bcmbal_subscriber_terminal_key_unpack, bcmbal_subscriber_terminal_key_scan };
+static bcmbal_group_info group_info_subscriber_terminal_cfg = { BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_subscriber_terminal_cfg_data), sizeof(bcmbal_subscriber_terminal_cfg), offsetof(bcmbal_subscriber_terminal_cfg, data), (bcmbal_func_packed_len) bcmbal_subscriber_terminal_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_subscriber_terminal_cfg_data_pack, (bcmbal_func_unpack) bcmbal_subscriber_terminal_cfg_data_unpack, bcmbal_subscriber_terminal_cfg_data_scan };
+static bcmbal_group_info group_info_subscriber_terminal_stat = { BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_STAT, 0, sizeof(bcmbal_subscriber_terminal_stat_data), sizeof(bcmbal_subscriber_terminal_stat), offsetof(bcmbal_subscriber_terminal_stat, data), (bcmbal_func_packed_len) bcmbal_subscriber_terminal_stat_data_get_packed_length, (bcmbal_func_pack) bcmbal_subscriber_terminal_stat_data_pack, (bcmbal_func_unpack) bcmbal_subscriber_terminal_stat_data_unpack, bcmbal_subscriber_terminal_stat_data_scan };
+static bcmbal_group_info group_info_subscriber_terminal_ind = { BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_subscriber_terminal_ind_data), sizeof(bcmbal_subscriber_terminal_ind), offsetof(bcmbal_subscriber_terminal_ind, data), (bcmbal_func_packed_len) bcmbal_subscriber_terminal_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_subscriber_terminal_ind_data_pack, (bcmbal_func_unpack) bcmbal_subscriber_terminal_ind_data_unpack, bcmbal_subscriber_terminal_ind_data_scan };
+static bcmbal_group_info group_info_tm_queue_key = { BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_tm_queue_key), 0, 0, (bcmbal_func_packed_len) bcmbal_tm_queue_key_get_packed_length, (bcmbal_func_pack) bcmbal_tm_queue_key_pack, (bcmbal_func_unpack) bcmbal_tm_queue_key_unpack, bcmbal_tm_queue_key_scan };
+static bcmbal_group_info group_info_tm_queue_cfg = { BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_tm_queue_cfg_data), sizeof(bcmbal_tm_queue_cfg), offsetof(bcmbal_tm_queue_cfg, data), (bcmbal_func_packed_len) bcmbal_tm_queue_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_tm_queue_cfg_data_pack, (bcmbal_func_unpack) bcmbal_tm_queue_cfg_data_unpack, bcmbal_tm_queue_cfg_data_scan };
+static bcmbal_group_info group_info_tm_queue_stat = { BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_STAT, 0, sizeof(bcmbal_tm_queue_stat_data), sizeof(bcmbal_tm_queue_stat), offsetof(bcmbal_tm_queue_stat, data), (bcmbal_func_packed_len) bcmbal_tm_queue_stat_data_get_packed_length, (bcmbal_func_pack) bcmbal_tm_queue_stat_data_pack, (bcmbal_func_unpack) bcmbal_tm_queue_stat_data_unpack, bcmbal_tm_queue_stat_data_scan };
+static bcmbal_group_info group_info_tm_queue_ind = { BCMBAL_OBJ_ID_TM_QUEUE, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_tm_queue_ind_data), sizeof(bcmbal_tm_queue_ind), offsetof(bcmbal_tm_queue_ind, data), (bcmbal_func_packed_len) bcmbal_tm_queue_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_tm_queue_ind_data_pack, (bcmbal_func_unpack) bcmbal_tm_queue_ind_data_unpack, bcmbal_tm_queue_ind_data_scan };
+static bcmbal_group_info group_info_tm_sched_key = { BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_KEY, 0, sizeof(bcmbal_tm_sched_key), 0, 0, (bcmbal_func_packed_len) bcmbal_tm_sched_key_get_packed_length, (bcmbal_func_pack) bcmbal_tm_sched_key_pack, (bcmbal_func_unpack) bcmbal_tm_sched_key_unpack, bcmbal_tm_sched_key_scan };
+static bcmbal_group_info group_info_tm_sched_cfg = { BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_CFG, 0, sizeof(bcmbal_tm_sched_cfg_data), sizeof(bcmbal_tm_sched_cfg), offsetof(bcmbal_tm_sched_cfg, data), (bcmbal_func_packed_len) bcmbal_tm_sched_cfg_data_get_packed_length, (bcmbal_func_pack) bcmbal_tm_sched_cfg_data_pack, (bcmbal_func_unpack) bcmbal_tm_sched_cfg_data_unpack, bcmbal_tm_sched_cfg_data_scan };
+static bcmbal_group_info group_info_tm_sched_ind = { BCMBAL_OBJ_ID_TM_SCHED, BCMBAL_MGT_GROUP_AUTO, 0, sizeof(bcmbal_tm_sched_ind_data), sizeof(bcmbal_tm_sched_ind), offsetof(bcmbal_tm_sched_ind, data), (bcmbal_func_packed_len) bcmbal_tm_sched_ind_data_get_packed_length, (bcmbal_func_pack) bcmbal_tm_sched_ind_data_pack, (bcmbal_func_unpack) bcmbal_tm_sched_ind_data_unpack, bcmbal_tm_sched_ind_data_scan };
+static bcmbal_group_info *group_info[] = { &group_info_access_terminal_key, &group_info_access_terminal_cfg, &group_info_access_terminal_ind, &group_info_flow_key, &group_info_flow_cfg, &group_info_flow_stat, &group_info_flow_ind, &group_info_group_key, &group_info_group_cfg, &group_info_interface_key, &group_info_interface_cfg, &group_info_interface_stat, &group_info_interface_ind, &group_info_packet_key, &group_info_packet_cfg, &group_info_packet_ind, &group_info_subscriber_terminal_key, &group_info_subscriber_terminal_cfg, &group_info_subscriber_terminal_stat, &group_info_subscriber_terminal_ind, &group_info_tm_queue_key, &group_info_tm_queue_cfg, &group_info_tm_queue_stat, &group_info_tm_queue_ind, &group_info_tm_sched_key, &group_info_tm_sched_cfg, &group_info_tm_sched_ind };
+static bcmbal_obj_group_id group_ids_access_terminal_key[] = { BCMBAL_OBJ_GROUP_ID_ACCESS_TERMINAL_KEY };
+static bcmbal_obj_group_id group_ids_access_terminal_cfg[] = { BCMBAL_OBJ_GROUP_ID_ACCESS_TERMINAL_CFG };
+static bcmbal_obj_group_id group_ids_access_terminal_auto[] = { BCMBAL_OBJ_GROUP_ID_ACCESS_TERMINAL_IND };
+static bcmbal_obj_group_id group_ids_flow_key[] = { BCMBAL_OBJ_GROUP_ID_FLOW_KEY };
+static bcmbal_obj_group_id group_ids_flow_cfg[] = { BCMBAL_OBJ_GROUP_ID_FLOW_CFG };
+static bcmbal_obj_group_id group_ids_flow_stat[] = { BCMBAL_OBJ_GROUP_ID_FLOW_STAT };
+static bcmbal_obj_group_id group_ids_flow_auto[] = { BCMBAL_OBJ_GROUP_ID_FLOW_IND };
+static bcmbal_obj_group_id group_ids_group_key[] = { BCMBAL_OBJ_GROUP_ID_GROUP_KEY };
+static bcmbal_obj_group_id group_ids_group_cfg[] = { BCMBAL_OBJ_GROUP_ID_GROUP_CFG };
+static bcmbal_obj_group_id group_ids_interface_key[] = { BCMBAL_OBJ_GROUP_ID_INTERFACE_KEY };
+static bcmbal_obj_group_id group_ids_interface_cfg[] = { BCMBAL_OBJ_GROUP_ID_INTERFACE_CFG };
+static bcmbal_obj_group_id group_ids_interface_stat[] = { BCMBAL_OBJ_GROUP_ID_INTERFACE_STAT };
+static bcmbal_obj_group_id group_ids_interface_auto[] = { BCMBAL_OBJ_GROUP_ID_INTERFACE_IND };
+static bcmbal_obj_group_id group_ids_packet_key[] = { BCMBAL_OBJ_GROUP_ID_PACKET_KEY };
+static bcmbal_obj_group_id group_ids_packet_cfg[] = { BCMBAL_OBJ_GROUP_ID_PACKET_CFG };
+static bcmbal_obj_group_id group_ids_packet_auto[] = { BCMBAL_OBJ_GROUP_ID_PACKET_IND };
+static bcmbal_obj_group_id group_ids_subscriber_terminal_key[] = { BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_KEY };
+static bcmbal_obj_group_id group_ids_subscriber_terminal_cfg[] = { BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_CFG };
+static bcmbal_obj_group_id group_ids_subscriber_terminal_stat[] = { BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_STAT };
+static bcmbal_obj_group_id group_ids_subscriber_terminal_auto[] = { BCMBAL_OBJ_GROUP_ID_SUBSCRIBER_TERMINAL_IND };
+static bcmbal_obj_group_id group_ids_tm_queue_key[] = { BCMBAL_OBJ_GROUP_ID_TM_QUEUE_KEY };
+static bcmbal_obj_group_id group_ids_tm_queue_cfg[] = { BCMBAL_OBJ_GROUP_ID_TM_QUEUE_CFG };
+static bcmbal_obj_group_id group_ids_tm_queue_stat[] = { BCMBAL_OBJ_GROUP_ID_TM_QUEUE_STAT };
+static bcmbal_obj_group_id group_ids_tm_queue_auto[] = { BCMBAL_OBJ_GROUP_ID_TM_QUEUE_IND };
+static bcmbal_obj_group_id group_ids_tm_sched_key[] = { BCMBAL_OBJ_GROUP_ID_TM_SCHED_KEY };
+static bcmbal_obj_group_id group_ids_tm_sched_cfg[] = { BCMBAL_OBJ_GROUP_ID_TM_SCHED_CFG };
+static bcmbal_obj_group_id group_ids_tm_sched_auto[] = { BCMBAL_OBJ_GROUP_ID_TM_SCHED_IND };
+static bcmbal_group_ids group_ids_obj_access_terminal[] = { { 1, group_ids_access_terminal_key }, { 1, group_ids_access_terminal_cfg }, { 0, NULL }, { 1, group_ids_access_terminal_auto }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_flow[] = { { 1, group_ids_flow_key }, { 1, group_ids_flow_cfg }, { 1, group_ids_flow_stat }, { 1, group_ids_flow_auto }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_group[] = { { 1, group_ids_group_key }, { 1, group_ids_group_cfg }, { 0, NULL }, { 0, NULL }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_interface[] = { { 1, group_ids_interface_key }, { 1, group_ids_interface_cfg }, { 1, group_ids_interface_stat }, { 1, group_ids_interface_auto }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_packet[] = { { 1, group_ids_packet_key }, { 1, group_ids_packet_cfg }, { 0, NULL }, { 1, group_ids_packet_auto }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_subscriber_terminal[] = { { 1, group_ids_subscriber_terminal_key }, { 1, group_ids_subscriber_terminal_cfg }, { 1, group_ids_subscriber_terminal_stat }, { 1, group_ids_subscriber_terminal_auto }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_tm_queue[] = { { 1, group_ids_tm_queue_key }, { 1, group_ids_tm_queue_cfg }, { 1, group_ids_tm_queue_stat }, { 1, group_ids_tm_queue_auto }, { 0, NULL } };
+static bcmbal_group_ids group_ids_obj_tm_sched[] = { { 1, group_ids_tm_sched_key }, { 1, group_ids_tm_sched_cfg }, { 0, NULL }, { 1, group_ids_tm_sched_auto }, { 0, NULL } };
+static bcmbal_group_ids *group_ids[] = { group_ids_obj_access_terminal, group_ids_obj_flow, group_ids_obj_group, group_ids_obj_interface, group_ids_obj_packet, group_ids_obj_subscriber_terminal, group_ids_obj_tm_queue, group_ids_obj_tm_sched };
+static bcmbal_presence_mask readonly_prop_mask[] = { (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_OPER_STATUS) | (1ULL << BCMBAL_ACCESS_TERMINAL_CFG_ID_IWF_MODE), 1ULL << BCMBAL_FLOW_CFG_ID_OPER_STATUS, (1ULL << BCMBAL_GROUP_CFG_ID_FLOWS) | (1ULL << BCMBAL_GROUP_CFG_ID_OWNER), (1ULL << BCMBAL_INTERFACE_CFG_ID_OPER_STATUS) | (1ULL << BCMBAL_INTERFACE_CFG_ID_SUB_TERM_ID_LIST), 0, (((1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_OPER_STATUS) | (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID)) | (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_SVC_PORT_ID_LIST)) | (1ULL << BCMBAL_SUBSCRIBER_TERMINAL_CFG_ID_AGG_PORT_ID_LIST), (1ULL << BCMBAL_TM_QUEUE_CFG_ID_CREATION_MODE) | (1ULL << BCMBAL_TM_QUEUE_CFG_ID_REF_COUNT), ((1ULL << BCMBAL_TM_SCHED_CFG_ID_CREATION_MODE) | (1ULL << BCMBAL_TM_SCHED_CFG_ID_QUEUES)) | (1ULL << BCMBAL_TM_SCHED_CFG_ID_SUB_SCHEDS) };
+static bcmbal_instance_info instance_info[] = { { offsetof(bcmbal_access_terminal_key, access_term_id), sizeof(bcmbal_access_id) }, { offsetof(bcmbal_flow_key, flow_id), sizeof(bcmbal_flow_id) }, { offsetof(bcmbal_group_key, group_id), sizeof(bcmbal_group_id) }, { offsetof(bcmbal_interface_key, intf_id), sizeof(uint32_t) }, { offsetof(bcmbal_packet_key, reserved), sizeof(uint32_t) }, { offsetof(bcmbal_subscriber_terminal_key, sub_term_id), sizeof(bcmbal_sub_id) }, { offsetof(bcmbal_tm_queue_key, id), sizeof(bcmbal_tm_queue_id) }, { offsetof(bcmbal_tm_sched_key, id), sizeof(bcmbal_tm_sched_id) } };
+
+/** Converts a specific object type, group and subgroup into a generic group ID.
+ *
+ * \param obj The object type that corresponds to the group ID.
+ * \param group The group type that corresponds to the group ID.
+ * \param subgroup The subgroup index that corresponds to the group ID.
+ * \param group_id The generic group ID.
+ * \return An error code or BCM_ERR_OK for success.
+ */
+static bcmos_errno _bcmbal_obj_group_id_combine(bcmbal_obj_id obj, bcmbal_mgt_group group, uint16_t subgroup, bcmbal_obj_group_id *group_id)
+{
+ if ((obj >= BCMBAL_OBJ_ID__NUM_OF) || (group >= BCMBAL_MGT_GROUP__NUM_OF) || (group_ids[obj] == NULL) || (subgroup >= group_ids[obj][group].subgroup_count))
+ {
+ return BCM_ERR_RANGE;
+ }
+
+ *group_id = group_ids[obj][group].subgroup_ids[subgroup];
+ return BCM_ERR_OK;
+}
+
+/******************************************************************************/
+static bcmos_bool _bcmbal_get_group_info(const bcmbal_obj *msg, bcmbal_group_info **group, bcmbal_group_info **key)
+{
+ bcmbal_obj_group_id group_id;
+ bcmbal_obj_group_id key_id;
+ bcmos_errno err;
+
+ err = _bcmbal_obj_group_id_combine(msg->obj_type, msg->group, msg->subgroup, &group_id);
+ if (err != BCM_ERR_OK)
+ {
+ return BCMOS_FALSE;
+ }
+
+ err = _bcmbal_obj_group_id_combine(msg->obj_type, BCMBAL_MGT_GROUP_KEY, 0, &key_id);
+ if (err != BCM_ERR_OK)
+ {
+ return BCMOS_FALSE;
+ }
+
+ *group = group_info[group_id];
+ *key = group_info[key_id];
+ return BCMOS_TRUE;
+}
+
+/** Gets the number of bytes a message would occupy when packed.
+ *
+ * \param msg The message to scan.
+ * \return The size in bytes if > 0, or an error as defined in bcmos_errno.
+ */
+static int32_t _bcmbal_obj_msg_packed_length_get(bcmbal_obj *msg)
+{
+ uint8_t *key_ptr;
+ bcmbal_group_info *group;
+ bcmbal_group_info *key;
+ int32_t ret;
+
+ /* First, get the total length of the packed BAL msg header and the packed BAL object header */
+ ret = bcmbal_bal_msg_hdr_get_packed_length() + bcmbal_obj_msg_hdr_get_packed_length();
+
+ if (!_bcmbal_get_group_info(msg, &group, &key))
+ {
+ return (int32_t) BCM_ERR_MSG_ERROR;
+ }
+
+ key_ptr = (uint8_t *) (msg + 1);
+
+ /* Add the length of the packed key */
+ ret += key->get_packed_length(key_ptr, BCMBAL_PRESENCE_MASK_ALL);
+
+ /* Add the length of the packed object itself (for those attributes that have been specified, if any) */
+ if (bcmbal_obj_msg_should_pack_data(msg) && (group->get_packed_length != NULL))
+ {
+ uint8_t *data_ptr = (uint8_t *) ((long)msg + group->data_offset);
+ ret += group->get_packed_length(data_ptr, msg->presence_mask);
+ }
+
+ return ret;
+}
+
+/** Packs a message to a byte stream.
+ *
+ * \param msg The message to pack.
+ * \param buf The stream to pack into.
+ * \return An error code or BCM_ERR_OK for success.
+ */
+static bcmos_errno _bcmbal_obj_msg_pack(bal_comm_msg_hdr *msg, bcmbal_buf *buf)
+{
+ uint8_t *key_ptr;
+ bcmos_errno err;
+ bcmbal_group_info *group;
+ bcmbal_group_info *key;
+ bcmbal_obj *bal_obj = (bcmbal_obj *)bcmbal_payload_ptr_get(msg);
+
+ if (!_bcmbal_get_group_info(bal_obj, &group, &key))
+ {
+ return BCM_ERR_MSG_ERROR;
+ }
+
+ err = bcmbal_bal_msg_hdr_pack(msg, buf);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ err = bcmbal_obj_msg_hdr_pack(bal_obj, buf);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ key_ptr = (uint8_t *) (bal_obj + 1);
+ if (!key->pack(key_ptr, buf, BCMBAL_PRESENCE_MASK_ALL))
+ {
+ return BCM_ERR_OVERFLOW;
+ }
+
+ if (bcmbal_obj_msg_should_pack_data(bal_obj) && (group->pack != NULL))
+ {
+ uint8_t *data_ptr = (uint8_t *) ((long)bal_obj + group->data_offset);
+ if (!group->pack(data_ptr, buf, bal_obj->presence_mask))
+ {
+ return BCM_ERR_OVERFLOW;
+ }
+ }
+
+ return err;
+}
+
+/* scan the input buffer to determine how much memory will be required to unpack variable-sized lists */
+static bcmos_errno bcmbal_obj_msg_list_mem_scan(bcmbal_buf *buf, const bcmbal_obj *hdr, const bcmbal_group_info *group, const bcmbal_group_info *key, uint32_t *size)
+{
+ uint32_t pos_before_scan = bcmbal_buf_get_used(buf);
+
+ if (!key->mem_scan(buf, size, BCMBAL_PRESENCE_MASK_ALL))
+ {
+ return BCM_ERR_OVERFLOW;
+ }
+
+ if (bcmbal_obj_msg_should_pack_data(hdr) && (group->mem_scan != NULL) && !group->mem_scan(buf, size, hdr->presence_mask))
+ {
+ return BCM_ERR_OVERFLOW;
+ }
+
+ if (!bcmbal_buf_rewind(buf, bcmbal_buf_get_used(buf) - pos_before_scan))
+ {
+ return BCM_ERR_OVERFLOW;
+ }
+
+ return BCM_ERR_OK;
+}
+
+/** Unpacks a message from a byte stream.
+ *
+ * This unpacks the message from the packed form into the struct following the "unpacked" pointer. There are several
+ * special cases:
+ *
+ * if *unpacked == NULL:
+ * *unpacked will be allocated dynamically via bcmos_calloc, in a contiguous block of memory with the struct
+ * itself followed by the memory required for all variable-sized lists.
+ *
+ * if (*unpacked)->list_buf != NULL:
+ * When a variable-length list is encountered in the input stream, and the array field we're unpacking into is NULL,
+ * memory will be allocated starting from (*unpacked)->list_buf. If multiple such lists exist, they will share this
+ * buffer. If the (*unpacked)->list_buf_size is not large enough, this will return BCM_ERR_INSUFFICIENT_LIST_MEM.
+ *
+ * \param buf The stream to unpack from.
+ * \param unpacked A pointer to the resulting unpacked BAL message starting at the bal header.
+ * \return The number of bytes unpacked if > 0, or an error as defined in bcmos_errno.
+ */
+static int32_t _bcmbal_obj_msg_unpack(bcmbal_buf *buf, bal_comm_msg_hdr **unpacked)
+{
+ bcmbal_obj bal_obj_hdr;
+ bal_comm_msg_hdr *bal_msg_hdr = &bal_obj_hdr.comm_hdr;
+ bcmos_errno err;
+ bcmbal_group_info *group;
+ bcmbal_group_info *key;
+ bcmos_bool did_malloc = BCMOS_FALSE;
+ uint8_t *key_ptr;
+ void *list_mem = NULL;
+ void **list_mem_ptr = NULL;
+ uint32_t size = 0;
+ bcmbal_obj *unpacked_bal_obj;
+
+ /* Preserve header fields that are not packed */
+ if (*unpacked != NULL)
+ memcpy(&bal_obj_hdr, bcmbal_payload_ptr_get(*unpacked), sizeof(bal_obj_hdr));
+ else
+ memset(&bal_obj_hdr, 0, sizeof(bal_obj_hdr));
+
+ err = bcmbal_bal_msg_hdr_unpack(bal_msg_hdr, buf);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ err = bcmbal_obj_msg_hdr_unpack(&bal_obj_hdr, buf);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ if (!_bcmbal_get_group_info(&bal_obj_hdr, &group, &key))
+ {
+ return BCM_ERR_MSG_ERROR;
+ }
+
+ /* If the caller did not allocate a space to unpack into, then alloc one */
+ if (*unpacked == NULL)
+ {
+ size = group->container_size == 0 ? sizeof(bcmbal_obj) + key->size : group->container_size;
+
+ err = bcmbal_obj_msg_list_mem_scan(buf, &bal_obj_hdr, group, key, &size);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ /* allocate a bal msg header, and a BAL object with data length of "size" */
+ unpacked_bal_obj = bcmbal_msg_calloc(size);
+ if (unpacked_bal_obj == NULL)
+ {
+ return BCM_ERR_NOMEM;
+ }
+
+ *unpacked = bcmbal_bal_hdr_get(unpacked_bal_obj);
+
+ list_mem = (uint8_t *)unpacked_bal_obj + group->container_size;
+ list_mem_ptr = &list_mem;
+ did_malloc = BCMOS_TRUE;
+ }
+ else
+ {
+ unpacked_bal_obj = bcmbal_payload_ptr_get(*unpacked);
+
+ if (unpacked_bal_obj->list_buf != NULL)
+ {
+ err = bcmbal_obj_msg_list_mem_scan(buf, &bal_obj_hdr, group, key, &size);
+ if (err != BCM_ERR_OK)
+ {
+ return err;
+ }
+
+ if (size > unpacked_bal_obj->list_buf_size)
+ {
+ return BCM_ERR_INSUFFICIENT_LIST_MEM;
+ }
+
+ list_mem = unpacked_bal_obj->list_buf;
+ list_mem_ptr = &list_mem;
+ }
+
+ size += group->container_size == 0 ? sizeof(bcmbal_obj) + key->size : group->container_size;
+ }
+
+ /* copy the bal message header into the unpack buffer */
+ bal_msg_hdr->m.size = size - sizeof(bcmos_msg);
+
+ /* copy the bal object header into the unpack buffer */
+ *unpacked_bal_obj = bal_obj_hdr;
+
+ key_ptr = (uint8_t *) (unpacked_bal_obj + 1);
+ if (!key->unpack(key_ptr, buf, list_mem_ptr, BCMBAL_PRESENCE_MASK_ALL))
+ {
+ if (did_malloc)
+ {
+ bcmbal_msg_free(unpacked_bal_obj);
+ *unpacked = NULL;
+ }
+
+ return BCM_ERR_OVERFLOW;
+ }
+
+ if (bcmbal_obj_msg_should_pack_data(&bal_obj_hdr))
+ {
+ uint8_t *data_ptr = (uint8_t *)unpacked_bal_obj + group->data_offset;
+ if ((group->unpack != NULL) && !group->unpack(data_ptr, buf, list_mem_ptr, unpacked_bal_obj->presence_mask))
+ {
+ if (did_malloc)
+ {
+ bcmbal_msg_free(unpacked_bal_obj);
+ *unpacked = NULL;
+ }
+
+ return BCM_ERR_OVERFLOW;
+ }
+ }
+
+ return size;
+}
+
+bcmos_errno bcmbal_obj_msg_pack(bal_comm_msg_hdr *unpacked_bal_msg, /* unpacked msg */ bcmos_msg **packed_msg) /* packed message */
+{
+ bcmbal_buf buf;
+ bcmos_errno ret;
+ bcmbal_obj *unpacked_obj;
+ int32_t packed_payload_len;
+ uint8_t *packed_payload;
+ bcmos_msg *os_msg;
+
+ *packed_msg = NULL; /* Initialization */
+
+ /* Recover a pointer to the UNPACKED bal object */
+ unpacked_obj = (bcmbal_obj *)bcmbal_payload_ptr_get(unpacked_bal_msg);
+
+ /* Calculate packed length */
+ packed_payload_len = _bcmbal_obj_msg_packed_length_get(unpacked_obj);
+ if (packed_payload_len < 0) return (bcmos_errno) packed_payload_len;
+
+ os_msg = (bcmos_msg *)bcmos_alloc(packed_payload_len + sizeof(bcmos_msg));
+
+ if (NULL == os_msg) return BCM_ERR_NORES;
+
+ memset(os_msg, 0, sizeof(bcmos_msg));
+ packed_payload = (uint8_t *) (os_msg + 1);
+ bcmbal_buf_init(&buf, packed_payload_len, packed_payload);
+ if (BCM_ERR_OK != (ret = _bcmbal_obj_msg_pack(unpacked_bal_msg, &buf)))
+ {
+ bcmos_free(os_msg);
+ return ret;
+ }
+
+ os_msg->data = packed_payload;
+ os_msg->size = packed_payload_len;
+ os_msg->type = unpacked_bal_msg->m.type;
+ os_msg->instance = unpacked_bal_msg->m.instance;
+ os_msg->sender = unpacked_bal_msg->m.sender;
+ *packed_msg = os_msg;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcmbal_obj_msg_unpack(bcmos_msg *packed_msg, /* packed message */ bal_comm_msg_hdr **unpacked_bal_msg) /* the unpacked bal msg */
+{
+ bcmbal_buf buf;
+ int32_t unpacked_len;
+ bal_comm_msg_hdr *bal_msg_hdr = *unpacked_bal_msg;
+ uint8_t *packed_payload = packed_msg->data;
+ uint32_t packed_payload_len = packed_msg->size;
+
+ bcmbal_buf_init(&buf, packed_payload_len, packed_payload);
+
+ unpacked_len = _bcmbal_obj_msg_unpack(&buf, &bal_msg_hdr);
+
+ if (unpacked_len < 0)
+ {
+ return (bcmos_errno) unpacked_len;
+ }
+
+ if (((bcmbal_obj *) (bcmbal_payload_ptr_get(bal_msg_hdr)))->version != BCMBAL_OBJ_VERSION)
+ {
+ bcmos_printf("Illegal BAL object version detected. Found: %d, Should be:%d\n", ((bcmbal_obj *) (bcmbal_payload_ptr_get(bal_msg_hdr)))->version, BCMBAL_OBJ_VERSION);
+
+ return BCM_ERR_PARSE;
+ }
+
+ *unpacked_bal_msg = bal_msg_hdr;
+
+ /* NOTE: Do NOT Free the passed in original received message! */
+ return BCM_ERR_OK;
+}
+
+bcmos_errno _bcmbal_obj_group_id_split(bcmbal_obj_group_id group_id, bcmbal_obj_id *obj, bcmbal_mgt_group *group, uint16_t *subgroup)
+{
+ if ((group_id >= BCMBAL_OBJ_GROUP_ID__NUM_OF) || (group_info[group_id] == NULL))
+ {
+ return BCM_ERR_RANGE;
+ }
+
+ *obj = group_info[group_id]->obj_type;
+ *group = group_info[group_id]->group;
+ *subgroup = group_info[group_id]->subgroup;
+ return BCM_ERR_OK;
+}
+
+/******************************************************************************/
+uint8_t bcmbal_obj_msg_instance(const bcmbal_obj *msg)
+{
+ const void *val_ptr;
+
+ if (msg->obj_type >= BCMBAL_OBJ_ID__NUM_OF)
+ {
+ return 0;
+ }
+
+ if (instance_info[msg->obj_type].offset < 0)
+ {
+ return 0;
+ }
+
+ val_ptr = ((const uint8_t *)(msg + 1)) + instance_info[msg->obj_type].offset;
+
+ /** This is probably not the smartest way to do this... TODO: revisit */
+ switch (instance_info[msg->obj_type].size)
+ {
+ case 1:
+ return *((const uint8_t *)val_ptr);
+ case 2:
+ return (uint8_t) (*((const uint16_t *)val_ptr));
+ case 4:
+ return (uint8_t) (*((const uint32_t *)val_ptr));
+ case 8:
+ return (uint8_t) (*((const uint64_t *)val_ptr));
+ default:
+ return 0;
+ }
+}
+
+/******************************************************************************/
+bcmos_errno bcmbal_obj_msg_clone(bal_comm_msg_hdr **dest, bal_comm_msg_hdr *src)
+{
+ bcmos_errno err;
+ int32_t packed_obj_msg_len;
+ uint8_t *mem;
+ bcmbal_buf buf;
+
+ packed_obj_msg_len = _bcmbal_obj_msg_packed_length_get(bcmbal_payload_ptr_get(src));
+ if (packed_obj_msg_len < 0)
+ {
+ return (bcmos_errno) packed_obj_msg_len;
+ }
+
+ /* Allocate a BAL msg (this includes the BAL msg hdr PLUS the BAL object) */
+ mem = bcmos_calloc((uint32_t) packed_obj_msg_len);
+ if (mem == NULL)
+ {
+ return BCM_ERR_NOMEM;
+ }
+
+ bcmbal_buf_init(&buf, (uint32_t) packed_obj_msg_len, mem);
+ err = _bcmbal_obj_msg_pack(src, &buf);
+ if (err != BCM_ERR_OK)
+ {
+ bcmos_free(mem);
+ return err;
+ }
+
+ buf.curr = buf.start;
+ err = _bcmbal_obj_msg_unpack(&buf, dest);
+ bcmos_free(mem);
+ return err;
+}
+
+/******************************************************************************/
+bcmos_errno bcmbal_get_prop_readonly_mask(bcmbal_obj_id obj, bcmbal_presence_mask *mask)
+{
+ if (obj >= BCMBAL_OBJ_ID__NUM_OF)
+ {
+ return BCM_ERR_RANGE;
+ }
+
+ *mask = readonly_prop_mask[obj];
+ return BCM_ERR_OK;
+}
diff --git a/bal_release/src/lib/libobjmsg/bal_obj_msg_pack_unpack.h b/bal_release/src/lib/libobjmsg/bal_obj_msg_pack_unpack.h
new file mode 100644
index 0000000..1837a99
--- /dev/null
+++ b/bal_release/src/lib/libobjmsg/bal_obj_msg_pack_unpack.h
@@ -0,0 +1,51 @@
+#ifndef BAL_OBJ_MSG_PACK_UNPACK_H_
+#define BAL_OBJ_MSG_PACK_UNPACK_H_
+
+#include "bcmos_system.h"
+#include "bcmos_errno.h"
+#include "bal_model_types.h"
+#include "bal_model_funcs.h"
+
+
+bcmos_errno bcmbal_obj_msg_pack(bal_comm_msg_hdr *unpacked_bal_msg,/* unpacked msg */
+ bcmos_msg **packed_msg); /* packed message */
+
+bcmos_errno bcmbal_obj_msg_unpack(bcmos_msg *packed_msg, /* packed message */
+ bal_comm_msg_hdr **unpacked_bal_msg); /* the unpacked bal msg */
+
+/** Returns the instance number of a given message, as determined by the object key.
+ *
+ * \param msg The message to check.
+ * \return The instance number of the message.
+ */
+uint8_t bcmbal_obj_msg_instance(const bcmbal_obj *msg);
+
+/** Gets a mask of all readonly properties for an object's cfg group.
+ *
+ * \param obj The objecct to check.
+ * \param mask A mask of bits set to 1 per read-only property.
+ * \return An error code or BCM_ERR_OK for success.
+ */
+bcmos_errno bcmbal_get_prop_readonly_mask(bcmbal_obj_id obj, bcmbal_presence_mask *mask);
+
+/** Clones a message by packing it to a buffer then unpacking it into the destination message.
+ * This uses _bcmbal_obj_msg_unpack, so if *dest is NULL, memory will by allocated dynamically using bcmos_calloc.
+ *
+ * \param dest A pointer to the location in memory that will hold the cloned message.
+ * \param src The message that should be copied.
+ * \return An error code or BCM_ERR_OK for success.
+ */
+bcmos_errno bcmbal_obj_msg_clone(bal_comm_msg_hdr **dest, bal_comm_msg_hdr *src);
+
+/** Converts a generic group ID into a specific object type, group and subgroup.
+ *
+ * \param group_id The generic group ID.
+ * \param obj The object type that corresponds to the group ID.
+ * \param group The group type that corresponds to the group ID.
+ * \param subgroup The subgroup index that corresponds to the group ID.
+ * \return An error code or BCM_ERR_OK for success.
+ */
+bcmos_errno _bcmbal_obj_group_id_split(bcmbal_obj_group_id group_id, bcmbal_obj_id *obj, bcmbal_mgt_group *group, uint16_t *subgroup);
+
+
+#endif /* BAL_OBJ_MSG_PACK_UNPACK_H_ */
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
+
diff --git a/bal_release/src/lib/libtopology/Makefile b/bal_release/src/lib/libtopology/Makefile
new file mode 100644
index 0000000..7507881
--- /dev/null
+++ b/bal_release/src/lib/libtopology/Makefile
@@ -0,0 +1,36 @@
+###############################################################################
+#
+# <: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 = topology
+MOD_TYPE = lib
+MOD_DEPS = dev_log maple_sdk
+
+srcs = bcm_topo.c
+
diff --git a/bal_release/src/lib/libtopology/bcm_topo.c b/bal_release/src/lib/libtopology/bcm_topo.c
new file mode 100644
index 0000000..4b092a0
--- /dev/null
+++ b/bal_release/src/lib/libtopology/bcm_topo.c
@@ -0,0 +1,650 @@
+/******************************************************************************
+ *
+ * <: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 <bcmolt_math.h>
+#include "bcm_topo.h"
+
+#define BCM_TOPO_MAX_LINE_SIZE 256
+#define BCM_TOPO_MAX_NNI_DEVICES 1
+
+uint32_t g_max_nni_ports[BCM_TOPO_MAX_NNI_DEVICES] = {BCM_TOPO_MAX_NNI_PORTS};
+
+typedef struct bcm_topo_dev_context_t bcm_topo_dev_context_t;
+
+typedef struct
+{
+ bcm_topo_dev_context_t *dev; /* Back pointer to the physical device this PON belongs to */
+ bcmos_bool is_initialized;
+ uint32_t pon_id;
+ uint32_t logical_pon;
+ bcm_topo_pon_mode pon_mode;
+ uint32_t max_num_of_onus;
+ void *contexts[BCM_TOPO_PON_CONTEXT_ID__NUM_OF]; /* User context - 1 entry per user */
+} bcm_topo_pon_context_t;
+
+struct bcm_topo_dev_context_t
+{
+ bcm_topo_pon_mode pon_mode; /* Currently we do not allow more than one PON mode per device (e.g: GPONx8 + XGPONx4) */
+ bcmos_bool is_initialized;
+ uint32_t device_id;
+ uint32_t max_num_of_pons;
+ bcm_topo_pon_context_t pons[BCM_TOPO_MAX_NUM_OF_PONS_PER_DEV];
+};
+
+typedef struct
+{
+ bcmos_bool is_initialized;
+ bcm_topo_dev_context_t devs[BCM_TOPO_MAX_NUM_OF_DEVS];
+ bcm_topo_pon_context_t *logical_pon2physical_pon[BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS];
+} bcm_topo_context_t;
+
+static bcm_topo_context_t bcm_topo_context;
+
+#ifdef ENABLE_LOG
+static dev_log_id topo_log_id = DEV_LOG_INVALID_ID;
+#endif
+
+static int2str_t pon_mode2str[] =
+{
+ {BCM_TOPO_PON_MODE_GPON, "gpon"},
+ {BCM_TOPO_PON_MODE_XGPON, "xgpon"},
+ {BCM_TOPO_PON_MODE_XGS, "xgs"},
+ {BCM_TOPO_PON_MODE_EPON_TDMA, "epon_tdma"},
+ {BCM_TOPO_PON_MODE_EPON_1G, "epon_1g"},
+ {BCM_TOPO_PON_MODE_EPON_10G, "epon_10g"},
+ {-1},
+};
+
+static int2int_t pon_mode2max_num_of_pons[] =
+{
+ {BCM_TOPO_PON_MODE_GPON, 16},
+ {BCM_TOPO_PON_MODE_XGPON, 8},
+ {BCM_TOPO_PON_MODE_XGS, 2},
+ {BCM_TOPO_PON_MODE_EPON_TDMA, 8},
+ {BCM_TOPO_PON_MODE_EPON_1G, 16},
+ {BCM_TOPO_PON_MODE_EPON_10G, 8},
+ {-1},
+};
+
+const char *bcm_topo_dev_get_pon_mode_str(bcmolt_devid device_id)
+{
+ return int2str(pon_mode2str, bcm_topo_context.devs[device_id].pon_mode);
+}
+
+int bcm_topo_dev_get_max_pon(bcmolt_devid device_id)
+{
+ return int2int(pon_mode2max_num_of_pons, bcm_topo_context.devs[device_id].pon_mode);
+}
+
+bcm_topo_pon_mode bcm_topo_pon_get_pon_mode(uint32_t pon)
+{
+ bcmolt_devid device_id;
+ uint32_t physical_pon;
+ bcmos_errno rc;
+
+ rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon);
+ if (rc != BCM_ERR_OK)
+ return BCM_TOPO_PON_MODE_INVALID;
+
+ return bcm_topo_context.devs[device_id].pons[physical_pon].pon_mode;
+}
+
+bcm_topo_pon_family bcm_topo_pon_get_pon_family(uint32_t pon)
+{
+ switch (bcm_topo_pon_get_pon_mode(pon))
+ {
+ case BCM_TOPO_PON_MODE_GPON:
+ case BCM_TOPO_PON_MODE_XGPON:
+ case BCM_TOPO_PON_MODE_XGS:
+ return BCM_TOPO_PON_FAMILY_GPON;
+ case BCM_TOPO_PON_MODE_EPON_TDMA:
+ case BCM_TOPO_PON_MODE_EPON_1G:
+ case BCM_TOPO_PON_MODE_EPON_10G:
+ return BCM_TOPO_PON_FAMILY_EPON;
+ default:
+ return BCM_TOPO_PON_FAMILY_INVALID;
+ }
+}
+
+bcm_topo_pon_sub_family bcm_topo_pon_get_pon_sub_family(uint32_t pon)
+{
+ switch (bcm_topo_pon_get_pon_mode(pon))
+ {
+ case BCM_TOPO_PON_MODE_GPON:
+ return BCM_TOPO_PON_SUB_FAMILY_GPON;
+ case BCM_TOPO_PON_MODE_XGPON:
+ case BCM_TOPO_PON_MODE_XGS:
+ return BCM_TOPO_PON_SUB_FAMILY_XGPON;
+ case BCM_TOPO_PON_MODE_EPON_TDMA:
+ case BCM_TOPO_PON_MODE_EPON_1G:
+ case BCM_TOPO_PON_MODE_EPON_10G:
+ return BCM_TOPO_PON_SUB_FAMILY_EPON;
+ default:
+ return BCM_TOPO_PON_SUB_FAMILY_INVALID;
+ }
+}
+
+uint32_t bcm_topo_pon_get_max_num_of_onus(uint32_t pon)
+{
+ bcmolt_devid device_id;
+ uint32_t physical_pon;
+ bcmos_errno rc;
+
+ rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon);
+ if (rc != BCM_ERR_OK)
+ return BCM_TOPO_ERR_INVALID;
+
+ return bcm_topo_context.devs[device_id].pons[physical_pon].max_num_of_onus;
+}
+
+bcmos_bool bcm_topo_pon_is_valid(uint32_t pon)
+{
+ bcmolt_devid device_id;
+ uint32_t physical_pon;
+
+ if (bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon) != BCM_ERR_OK)
+ return BCMOS_FALSE;
+
+ return BCMOS_TRUE;
+}
+
+bcmolt_devid bcm_topo_dev_get_next(bcmolt_devid device_id)
+{
+ if (device_id == BCM_TOPO_DEV_INVALID)
+ device_id = 0;
+ else
+ device_id++;
+
+ for (; device_id < BCM_TOPO_MAX_NUM_OF_DEVS && !bcm_topo_context.devs[device_id].is_initialized; device_id++);
+
+ return device_id == BCM_TOPO_MAX_NUM_OF_DEVS ? BCM_TOPO_DEV_INVALID : device_id;
+}
+
+uint32_t bcm_topo_pon_get_next(bcmolt_devid device_id, uint32_t pon)
+{
+ uint32_t physical_pon;
+ bcmos_errno rc;
+
+ if (device_id >= BCM_TOPO_MAX_NUM_OF_DEVS)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Device ID must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_DEVS - 1);
+ return BCM_TOPO_PON_INVALID;
+ }
+
+ if (pon == BCM_TOPO_PON_INVALID)
+ physical_pon = 0;
+ else
+ {
+ bcmolt_devid dummy;
+
+ rc = bcm_topo_pon_get_logical2physical(pon, &dummy, &physical_pon);
+ if (rc != BCM_ERR_OK)
+ {
+ return BCM_TOPO_PON_INVALID;
+ }
+ else
+ {
+ physical_pon++;
+ }
+ }
+
+ if (physical_pon < bcm_topo_context.devs[device_id].max_num_of_pons)
+ {
+ rc = bcm_topo_pon_get_physical2logical(device_id, physical_pon, &pon);
+ if (rc != BCM_ERR_OK)
+ {
+ return BCM_TOPO_PON_INVALID;
+ }
+ else
+ {
+ return pon;
+ }
+ }
+
+ return BCM_TOPO_PON_INVALID;
+}
+
+bcmos_errno bcm_topo_pon_get_logical2physical(uint32_t logical_pon, bcmolt_devid *device_id, uint32_t *physical_pon)
+{
+ if (logical_pon >= BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Logical PON ID must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS - 1);
+ return BCM_ERR_RANGE;
+ }
+
+ if (!bcm_topo_context.logical_pon2physical_pon[logical_pon])
+ {
+ BCM_LOG(ERROR, topo_log_id, "Logical PON=%u was not associated with a physical PON\n", logical_pon);
+ return BCM_ERR_RANGE;
+ }
+
+ *physical_pon = bcm_topo_context.logical_pon2physical_pon[logical_pon]->pon_id;
+ *device_id = bcm_topo_context.logical_pon2physical_pon[logical_pon]->dev->device_id;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_topo_pon_get_physical2logical(bcmolt_devid device_id, uint32_t physical_pon, uint32_t *logical_pon)
+{
+ if (device_id >= BCM_TOPO_MAX_NUM_OF_DEVS)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Device ID must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_DEVS - 1);
+ return BCM_ERR_RANGE;
+ }
+
+ if (physical_pon >= bcm_topo_context.devs[device_id].max_num_of_pons)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Physical PON ID must be in the range 0 .. %u\n", bcm_topo_context.devs[device_id].max_num_of_pons - 1);
+ return BCM_ERR_RANGE;
+ }
+
+ if (bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon == BCM_TOPO_PON_INVALID)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Physical PON=%u on device=%u was not associated with a logical PON\n", physical_pon, device_id);
+ return BCM_ERR_RANGE;
+ }
+
+ *logical_pon = bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon;
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_topo_pon_set_context(uint32_t pon, bcm_topo_pon_context_id pon_context_id, void *context)
+{
+ bcmolt_devid device_id;
+ uint32_t physical_pon;
+ bcmos_errno rc;
+
+ if (pon_context_id >= BCM_TOPO_PON_CONTEXT_ID__NUM_OF)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Invalid PON context ID\n");
+ return BCM_ERR_RANGE;
+ }
+
+ rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon);
+ if (rc != BCM_ERR_OK)
+ return rc;
+
+ bcm_topo_context.devs[device_id].pons[physical_pon].contexts[pon_context_id] = context;
+
+ return BCM_ERR_OK;
+}
+
+void *bcm_topo_pon_get_context(uint32_t pon, bcm_topo_pon_context_id pon_context_id)
+{
+ bcmolt_devid device_id;
+ uint32_t physical_pon;
+ bcmos_errno rc;
+
+ if (pon_context_id >= BCM_TOPO_PON_CONTEXT_ID__NUM_OF)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Invalid PON context ID\n");
+ return NULL;
+ }
+
+ rc = bcm_topo_pon_get_logical2physical(pon, &device_id, &physical_pon);
+ if (rc != BCM_ERR_OK)
+ return NULL;
+
+ return bcm_topo_context.devs[device_id].pons[physical_pon].contexts[pon_context_id];
+}
+
+static void bcm_topo_init_context(void)
+{
+ uint32_t device_id;
+
+ for (device_id = 0; device_id < BCM_TOPO_MAX_NUM_OF_DEVS; device_id++)
+ {
+ bcm_topo_dev_context_t *dev;
+ uint32_t pon_id;
+
+ dev = &bcm_topo_context.devs[device_id];
+ dev->device_id = device_id;
+ dev->pon_mode = BCM_TOPO_PON_MODE_INVALID;
+ for (pon_id = 0; pon_id < BCM_TOPO_MAX_NUM_OF_PONS_PER_DEV; pon_id++)
+ {
+ bcm_topo_pon_context_t *pon;
+
+ pon = &dev->pons[pon_id];
+ pon->dev = dev;
+ pon->pon_id = pon_id;
+ pon->pon_mode = BCM_TOPO_PON_MODE_INVALID;
+ pon->logical_pon = BCM_TOPO_PON_INVALID;
+ }
+ }
+}
+
+static bcmos_errno bcm_topo_init_line_parse(const char *line, const char *filename, uint32_t line_num, bcmos_bool *is_skipped, uint32_t *logical_pon, bcm_topo_pon_mode *pon_mode,
+ uint32_t *device_id, uint32_t *physical_pon)
+{
+ int rc;
+ char logical_pon_str[BCM_TOPO_MAX_LINE_SIZE];
+ char pon_mode_str[BCM_TOPO_MAX_LINE_SIZE];
+ char device_id_str[BCM_TOPO_MAX_LINE_SIZE];
+ char physical_pon_str[BCM_TOPO_MAX_LINE_SIZE];
+ int2str_t *p;
+
+ /* Skip blank lines and comments. */
+ if (!*line || *line == '\n' || *line == '#')
+ {
+ *is_skipped = BCMOS_TRUE;
+ return BCM_ERR_OK;
+ }
+
+ *is_skipped = BCMOS_FALSE;
+
+ /* Read the tokens separated by commas. */
+ rc = sscanf(line, "%[^,],%*[ ]%[^,],%[^,],%[^\n]", logical_pon_str, pon_mode_str, device_id_str, physical_pon_str);
+ if (rc < 4)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc);
+ return BCM_ERR_PARSE;
+ }
+
+ if (sscanf(logical_pon_str, "%u", logical_pon) < 1)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc);
+ return BCM_ERR_PARSE;
+ }
+
+ if (sscanf(device_id_str, "%u", device_id) < 1)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc);
+ return BCM_ERR_PARSE;
+ }
+
+ if (sscanf(physical_pon_str, "%u", physical_pon) < 1)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Error parsing line %s:%u (rc=%u)\n", filename, line_num, rc);
+ return BCM_ERR_PARSE;
+ }
+
+ BCM_LOG(INFO, topo_log_id, "Map Logical PON ID=%u -> (Physical Device ID=%u, Physical Pon ID=%u, PON mode='%s')\n", *logical_pon, *device_id, *physical_pon, pon_mode_str);
+
+ for (p = pon_mode2str; p->from != -1 && strcmp(pon_mode_str, p->to); p++);
+
+ if (p->from == -1)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Error parsing PON mode at %s:%u\n", filename, line_num);
+ return BCM_ERR_PARSE;
+ }
+
+ *pon_mode = p->from;
+
+ return BCM_ERR_OK;
+}
+
+static void bcm_topo_init_dev(bcm_topo_dev_context_t *dev, bcm_topo_pon_mode pon_mode)
+{
+ dev->pon_mode = pon_mode;
+ dev->max_num_of_pons = int2int(pon_mode2max_num_of_pons, pon_mode);
+}
+
+static void bcm_topo_init_pon(bcm_topo_pon_context_t *pon, bcm_topo_pon_mode pon_mode)
+{
+ pon->pon_mode = pon_mode;
+ switch (pon_mode)
+ {
+ case BCM_TOPO_PON_MODE_GPON:
+ pon->max_num_of_onus = 128;
+ break;
+ case BCM_TOPO_PON_MODE_XGPON:
+ case BCM_TOPO_PON_MODE_XGS:
+ pon->max_num_of_onus = 256;
+ break;
+ case BCM_TOPO_PON_MODE_EPON_TDMA:
+ case BCM_TOPO_PON_MODE_EPON_1G:
+ case BCM_TOPO_PON_MODE_EPON_10G:
+ pon->max_num_of_onus = 0; /* There is no "ONU" in EPON, but LLIDs. */
+ break;
+ default:
+ break;
+ }
+}
+
+static bcmos_errno bcm_topo_init_by_file(FILE *fp, const char *filename)
+{
+ char line[BCM_TOPO_MAX_LINE_SIZE];
+ uint32_t line_num;
+
+ /* Read next line. */
+ line_num = 1;
+ while (fgets(line, sizeof(line), fp))
+ {
+ bcmos_bool is_skipped;
+ uint32_t logical_pon, device_id, physical_pon;
+ bcm_topo_pon_mode pon_mode;
+ bcm_topo_dev_context_t *dev;
+ bcm_topo_pon_context_t *pon;
+
+ if (bcm_topo_init_line_parse(line, filename, line_num, &is_skipped, &logical_pon, &pon_mode, &device_id, &physical_pon) != BCM_ERR_OK)
+ return BCM_ERR_PARSE;
+
+ if (is_skipped)
+ {
+ line_num++;
+ continue;
+ }
+
+ if (logical_pon >= BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Logical PON ID at %s:%u must be in the range 0 .. %u\n", filename, line_num, BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS - 1);
+ return BCM_ERR_RANGE;
+ }
+
+ if (bcm_topo_context.logical_pon2physical_pon[logical_pon])
+ {
+ BCM_LOG(ERROR, topo_log_id, "Logical PON ID at %s:%u has already been set before\n", filename, line_num);
+ return BCM_ERR_ALREADY;
+ }
+
+ if (device_id >= BCM_TOPO_MAX_NUM_OF_DEVS)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Physical device ID at %s:%u must be in the range 0 .. %u\n", filename, line_num, BCM_TOPO_MAX_NUM_OF_DEVS - 1);
+ return BCM_ERR_RANGE;
+ }
+
+ dev = &bcm_topo_context.devs[device_id];
+ if (!dev->is_initialized)
+ {
+ bcm_topo_init_dev(dev, pon_mode);
+ dev->is_initialized = BCMOS_TRUE;
+ }
+ else if (dev->pon_mode != pon_mode)
+ {
+ BCM_LOG(ERROR, topo_log_id, "PON mode at %s:%u conflicts with PON mode='%s' that has already been set for this device\n", filename, line_num,
+ int2str(pon_mode2str, dev->pon_mode));
+ return BCM_ERR_NOT_SUPPORTED;
+ }
+
+ if (physical_pon >= dev->max_num_of_pons)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Physical PON ID at %s:%u must be in the range 0 .. %u\n", filename, line_num, dev->max_num_of_pons - 1);
+ return BCM_ERR_RANGE;
+ }
+
+ pon = &bcm_topo_context.devs[device_id].pons[physical_pon];
+ if (!pon->is_initialized)
+ {
+ bcm_topo_init_pon(pon, pon_mode);
+ pon->is_initialized = BCMOS_TRUE;
+ }
+ else
+ {
+ BCM_LOG(ERROR, topo_log_id, "Physical PON ID at %s:%u has already been set before\n", filename, line_num);
+ return BCM_ERR_ALREADY;
+ }
+
+ bcm_topo_context.logical_pon2physical_pon[logical_pon] = &bcm_topo_context.devs[device_id].pons[physical_pon];
+ bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon = logical_pon;
+
+ line_num++;
+ }
+
+ return BCM_ERR_OK;
+}
+
+static bcmos_errno bcm_topo_init_by_args(bcm_topo_params *params)
+{
+ uint32_t device_id;
+ uint32_t max_num_of_pons_per_dev;
+
+ if (params->num_of_devs > BCM_TOPO_MAX_NUM_OF_DEVS)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Number of devices must be in the range 0 .. %u\n", BCM_TOPO_MAX_NUM_OF_DEVS);
+ return BCM_ERR_RANGE;
+ }
+
+ max_num_of_pons_per_dev = int2int(pon_mode2max_num_of_pons, params->pon_mode);
+
+ if (params->num_of_pons_per_dev > max_num_of_pons_per_dev)
+ {
+ BCM_LOG(ERROR, topo_log_id, "Number of PONs per device for PON mode '%s' must be in the range 0 .. %u\n", int2str(pon_mode2str, params->pon_mode), BCM_TOPO_MAX_NUM_OF_DEVS);
+ return BCM_ERR_RANGE;
+ }
+
+ for (device_id = 0; device_id < params->num_of_devs; device_id++)
+ {
+ uint32_t physical_pon;
+ bcm_topo_dev_context_t *dev;
+ bcm_topo_pon_context_t *pon;
+
+ dev = &bcm_topo_context.devs[device_id];
+ bcm_topo_init_dev(dev, params->pon_mode);
+ dev->is_initialized = BCMOS_TRUE;
+
+ for (physical_pon = 0; physical_pon < params->num_of_pons_per_dev; physical_pon++)
+ {
+ uint32_t logical_pon;
+
+ logical_pon = (device_id * params->num_of_pons_per_dev) + physical_pon;
+
+ BCM_LOG(INFO, topo_log_id, "Map Logical PON ID=%u -> (Physical Device ID=%u, Physical pon ID=%u, PON mode='%s')\n", logical_pon, device_id, physical_pon,
+ int2str(pon_mode2str, params->pon_mode));
+
+ pon = &bcm_topo_context.devs[device_id].pons[physical_pon];
+ bcm_topo_init_pon(pon, params->pon_mode);
+ pon->is_initialized = BCMOS_TRUE;
+
+ bcm_topo_context.logical_pon2physical_pon[logical_pon] = &bcm_topo_context.devs[device_id].pons[physical_pon];
+ bcm_topo_context.devs[device_id].pons[physical_pon].logical_pon = logical_pon;
+ }
+ }
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcm_topo_init(bcm_topo_params *params, const char *topo_filename)
+{
+ bcmos_errno ret;
+ FILE *topo_fp;
+
+#ifdef ENABLE_LOG
+ if (topo_log_id == DEV_LOG_INVALID_ID)
+ {
+ topo_log_id = bcm_dev_log_id_register("TOPOLOGY", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ BUG_ON(topo_log_id == DEV_LOG_INVALID_ID);
+ }
+#endif
+
+ bcm_topo_init_context();
+
+ topo_fp = fopen(topo_filename, "r");
+ if (topo_fp)
+ {
+ BCM_LOG(INFO, topo_log_id, "Topology is taken from file\n");
+ ret = bcm_topo_init_by_file(topo_fp, topo_filename);
+ fclose(topo_fp);
+ }
+ else if (params)
+ {
+ BCM_LOG(INFO, topo_log_id, "Topology is taken from arguments\n");
+ ret = bcm_topo_init_by_args(params);
+ }
+ else
+ {
+ BCM_LOG(INFO, topo_log_id, "At least one of topo_fp and params must be specified and exist\n");
+ ret = BCM_ERR_PARM;
+ }
+
+ if (ret != BCM_ERR_OK)
+ goto exit;
+
+ bcm_topo_context.is_initialized = BCMOS_TRUE;
+
+ ret = BCM_ERR_OK;
+
+exit:
+ return ret;
+}
+
+bcmos_bool bcm_topo_is_initialized(void)
+{
+ return bcm_topo_context.is_initialized;
+}
+
+bcmos_bool bcm_topo_dev_set_max_nni(bcmolt_devid device_id, uint32_t num_nni_ports)
+{
+ if(device_id >= BCM_TOPO_MAX_NNI_DEVICES)
+ {
+ return BCM_ERR_PARM;
+ }
+ /* make sure the max number does not exceed the allocated resrouce */
+ if( num_nni_ports > BCM_TOPO_MAX_NNI_PORTS)
+ {
+ return BCM_ERR_PARM;
+ }
+ g_max_nni_ports[device_id] = num_nni_ports;
+
+ return BCMOS_TRUE;
+}
+
+bcmos_bool bcm_topo_dev_get_max_nni(bcmolt_devid device_id, uint32_t *p_num_nni_ports)
+{
+ if(device_id >= BCM_TOPO_MAX_NNI_DEVICES)
+ {
+ return BCM_ERR_PARM;
+ }
+ *p_num_nni_ports = g_max_nni_ports[device_id];
+
+ return BCMOS_TRUE;
+}
+
+bcmos_bool bcm_topo_nni_is_valid(uint32_t nni)
+{
+
+ if (nni >= g_max_nni_ports[0])
+ return BCMOS_FALSE;
+
+ return BCMOS_TRUE;
+}
+
diff --git a/bal_release/src/lib/libtopology/bcm_topo.h b/bal_release/src/lib/libtopology/bcm_topo.h
new file mode 100644
index 0000000..9c6ec1c
--- /dev/null
+++ b/bal_release/src/lib/libtopology/bcm_topo.h
@@ -0,0 +1,270 @@
+/******************************************************************************
+ *
+ * <: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 _BCM_TOPO_H_
+#define _BCM_TOPO_H_
+
+#include <bcmolt_conv.h>
+#include <bcmos_system.h>
+#include <bcmolt_model_types.h>
+#include <bal_model_types.h>
+
+#define BCM_TOPO_DEV_INVALID UINT8_MAX
+#define BCM_TOPO_PON_INVALID UINT32_MAX
+#define BCM_TOPO_ERR_INVALID UINT32_MAX
+#define BCM_TOPO_MAX_NUM_OF_DEVS 8 /* Maxmimum of 8 devices per vOLT. */
+#define BCM_TOPO_MAX_NUM_OF_PONS_PER_DEV 16
+#define BCM_TOPO_MAX_NUM_OF_LOGICAL_PONS (BCM_TOPO_MAX_NUM_OF_DEVS * BCM_TOPO_MAX_NUM_OF_PONS_PER_DEV)
+
+#define BCM_TOPO_FOR_EACH_DEV(device_id) \
+ for (device_id = bcm_topo_dev_get_next(BCM_TOPO_DEV_INVALID); device_id != BCM_TOPO_DEV_INVALID; device_id = bcm_topo_dev_get_next(device_id))
+
+#define BCM_TOPO_DEV_FOR_EACH_PON(device_id, pon) \
+ for (pon = bcm_topo_pon_get_next(device_id, BCM_TOPO_PON_INVALID); pon != BCM_TOPO_PON_INVALID; pon = bcm_topo_pon_get_next(device_id, pon))
+
+#define BCM_TOPO_FOR_EACH_PON(device_id, pon) \
+ for (device_id = bcm_topo_dev_get_next(BCM_TOPO_DEV_INVALID); device_id != BCM_TOPO_DEV_INVALID; device_id = bcm_topo_dev_get_next(device_id)) \
+ BCM_TOPO_DEV_FOR_EACH_PON(device_id, pon)
+
+#define BCM_TOPO_FOR_EACH_ONU(pon, onu) \
+ for (onu = 0; onu < bcm_topo_pon_get_max_num_of_onus(pon); onu++)
+
+typedef enum
+{
+ BCM_TOPO_PON_MODE_GPON,
+ BCM_TOPO_PON_MODE_XGPON,
+ BCM_TOPO_PON_MODE_XGS,
+ BCM_TOPO_PON_MODE_EPON_TDMA,
+ BCM_TOPO_PON_MODE_EPON_1G,
+ BCM_TOPO_PON_MODE_EPON_10G,
+ BCM_TOPO_PON_MODE_INVALID,
+ BCM_TOPO_PON_MODE__NUM_OF,
+} bcm_topo_pon_mode;
+
+typedef enum
+{
+ BCM_TOPO_PON_FAMILY_GPON, /* GPON, XGPON, XGS, NGPON2 */
+ BCM_TOPO_PON_FAMILY_EPON,
+ BCM_TOPO_PON_FAMILY_INVALID,
+ BCM_TOPO_PON_FAMILY__NUM_OF,
+} bcm_topo_pon_family;
+
+typedef enum
+{
+ BCM_TOPO_PON_SUB_FAMILY_GPON, /* GPON only */
+ BCM_TOPO_PON_SUB_FAMILY_XGPON, /* XGPON, XGS, NGPON2 */
+ BCM_TOPO_PON_SUB_FAMILY_EPON,
+ BCM_TOPO_PON_SUB_FAMILY_INVALID,
+ BCM_TOPO_PON_SUB_FAMILY__NUM_OF,
+} bcm_topo_pon_sub_family;
+
+/* User context identifier - can be extended if more modules in the system use the bcm_topo.context. */
+typedef enum
+{
+ BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL,
+ BCM_TOPO_PON_CONTEXT_ID_OMCI_SVC,
+ BCM_TOPO_PON_CONTEXT_ID_RSC_MGR,
+ BCM_TOPO_PON_CONTEXT_ID__NUM_OF,
+} bcm_topo_pon_context_id;
+
+typedef struct
+{
+ uint32_t num_of_devs;
+ uint32_t num_of_pons_per_dev;
+ bcm_topo_pon_mode pon_mode;
+} bcm_topo_params;
+
+/**
+ * @brief Get the PON mode of a given device ID.
+ * @param device_id device ID
+ *
+ * @returns PON mode or Null on error
+ */
+const char *bcm_topo_dev_get_pon_mode_str(bcmolt_devid device_id);
+
+
+/**
+ * @brief Get the max number of pons of a given device ID.
+ * @param device_id device ID
+ *
+ * @returns the max number of pons or -1 on error
+ */
+int bcm_topo_dev_get_max_pon(bcmolt_devid device_id);
+
+/**
+ * @brief Get the PON mode of a given logical PON ID.
+ * @param pon Logical PON ID
+ *
+ * @returns PON mode or BCM_TOPO_PON_MODE_INVALID on error
+ */
+bcm_topo_pon_mode bcm_topo_pon_get_pon_mode(uint32_t pon);
+
+/**
+ * @brief Get the PON family of a given logical PON ID.
+ * @param pon Logical PON ID
+ *
+ * @returns PON mode or BCM_TOPO_PON_FAMILY_INVALID on error
+ */
+bcm_topo_pon_family bcm_topo_pon_get_pon_family(uint32_t pon);
+
+/**
+ * @brief Get the PON sub-family of a given logical PON ID.
+ * @param pon Logical PON ID
+ *
+ * @returns PON mode or BCM_TOPO_PON_SUB_FAMILY_INVALID on error
+ */
+bcm_topo_pon_sub_family bcm_topo_pon_get_pon_sub_family(uint32_t pon);
+
+/**
+ * @brief Get the number of ONUs of a given logical PON ID.
+ * @param pon Logical PON ID
+ *
+ * @returns Number of ONUs or BCM_TOPO_ERR_INVALID on error
+ */
+uint32_t bcm_topo_pon_get_max_num_of_onus(uint32_t pon);
+
+/**
+ * @brief Return whether a given logical PON is in the valid range.
+ *
+ * @returns BCMOS_TRUE is the given logical PON is in the valid range, BCMOS_FALSE otherwise
+ */
+bcmos_bool bcm_topo_pon_is_valid(uint32_t pon);
+
+/**
+ * @brief Traverse devices
+ * @param device_id Device iterator. Should be BCM_TOPO_DEV_INVALID at the beginning.
+ *
+ * @returns Next device, or BCM_TOPO_DEV_INVALID to mark that no more devices are available.
+ */
+bcmolt_devid bcm_topo_dev_get_next(bcmolt_devid device_id);
+
+/**
+ * @brief Traverse logical PONs within a given device.
+ * @param device_id Device id
+ * @param pon Logical PON iterator. Should be BCM_TOPO_PON_INVALID at the beginning.
+ *
+ * @returns Next logical PON on this device, or BCM_TOPO_PON_INVALID to mark that no more PONs are available.
+ */
+uint32_t bcm_topo_pon_get_next(bcmolt_devid device_id, uint32_t pon);
+
+/**
+ * @brief Get device ID and physical PON ID from logical PON ID.
+ * @param logical_pon logical PON ID
+ * @param *device_id Pointer to device id
+ * @param *physical_pon Pointer to physical PON ID
+ *
+ * @returns bcmos_errno
+ * @note In general, the physical PON ID is used in the hardware directed function calls.
+ */
+bcmos_errno bcm_topo_pon_get_logical2physical(uint32_t logical_pon, bcmolt_devid *device_id, uint32_t *physical_pon);
+
+/**
+ * @brief Get logical PON ID from device ID and physical PON ID.
+ * @param device_id Device id
+ * @param physical_pon Physical PON ID
+ * @param *logical_pon Pointer to logical PON ID
+ *
+ * @returns bcmos_errno
+ * @note In general, the logical PON ID is used in the BAL core directed function calls.
+ */
+bcmos_errno bcm_topo_pon_get_physical2logical(bcmolt_devid device_id, uint32_t physical_pon, uint32_t *logical_pon);
+
+/**
+ * @brief Set user context for a given logical PON ID.
+ * @param pon Logical PON ID
+ * @param pon_context_id The identity of the module using the context
+ * @param context Pointer to user context
+ *
+ * @returns bcmos_errno
+ */
+bcmos_errno bcm_topo_pon_set_context(uint32_t pon, bcm_topo_pon_context_id pon_context_id, void *context);
+
+/**
+ * @brief Get user context for a given logical PON ID.
+ * @param pon Logical PON ID
+ * @param pon_context_id The identity of the module using the context
+ *
+ * @returns User context or NULL if there's an error
+ */
+void *bcm_topo_pon_get_context(uint32_t pon, bcm_topo_pon_context_id pon_context_id);
+
+/**
+ * @brief Initialize topology module, either by arguments (probably received from CLI) or by a topology file. The rule is at least one of them must be specified and exist. If both are
+ * specified and exist, then we rely on topology file.
+ * Pay attention that when not using a file, the user have less freedom. For example:
+ * - The user won't be able to have devices with different PON modes.
+ * - The user won't be able to have devices with different number of PONs.
+ * - The user won't be able to map logical PON to (device, physical PON). We assume that logical_pon = (device * num_of_pons_per_dev) + physical_pon.
+ * @param params Topology parameters. If NULL, we rely on topology file.
+ * @param topo_filename File containing bcm_topo.configuration in a .csv format
+ * The columns are:
+ * Logical PON ID, PON Mode, Physical Device ID, Physical PON ID
+ *
+ * @returns bcmos_errno
+ */
+bcmos_errno bcm_topo_init(bcm_topo_params *params, const char *topo_filename);
+
+/**
+ * @brief Returns whether the topology module has been initialized.
+ *
+ * @returns BCMOS_TRUE if topology module has been initialized
+ */
+bcmos_bool bcm_topo_is_initialized(void);
+
+#define BCM_TOPO_MAX_NNI_PORTS 16
+
+/**
+ * @brief Set the max number of nnis of a given device ID.
+ * @param device_id device ID
+ * @param num_nni_ports nni ports on the device
+ *
+ * @returns BCMOS_TRUE
+ */
+bcmos_bool bcm_topo_dev_set_max_nni(bcmolt_devid device_id, uint32_t num_nni_ports);
+
+/**
+ * @brief Get the max number of nnis of a given device ID.
+ * @param device_id device ID
+ * @param p_num_nni_ports pointer for the retrieved nni ports on the device
+ *
+ * @returns BCMOS_TRUE
+ */
+bcmos_bool bcm_topo_dev_get_max_nni(bcmolt_devid device_id, uint32_t *p_num_nni_ports);
+
+/**
+ * @brief Return whether a given logical NNI is in the valid range.
+ *
+ * @returns BCMOS_TRUE is the given logical NNI is in the valid range, BCMOS_FALSE otherwise
+ */
+bcmos_bool bcm_topo_nni_is_valid(uint32_t nni);
+
+#endif
+
diff --git a/bal_release/src/lib/libutils/Makefile b/bal_release/src/lib/libutils/Makefile
new file mode 100644
index 0000000..8b4dd50
--- /dev/null
+++ b/bal_release/src/lib/libutils/Makefile
@@ -0,0 +1,35 @@
+###############################################################################
+#
+# <: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 = balutils
+MOD_TYPE = lib
+
+srcs = bal_utils.c
+
diff --git a/bal_release/src/lib/libutils/bal_utils.c b/bal_release/src/lib/libutils/bal_utils.c
new file mode 100644
index 0000000..024b3d9
--- /dev/null
+++ b/bal_release/src/lib/libutils/bal_utils.c
@@ -0,0 +1,541 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_utils.c
+ * @brief BAL Utilities source
+ *
+ * This file contains the implementation of various BAL "utilities",
+ * which are provided via the libutils.a library.
+ */
+
+/*@{*/
+
+#ifdef USING_BAL_UTILS
+
+/* --- system includes ---*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+#include <bcmos_system.h>
+
+/* --- project includes ---*/
+#include "bal_utils.h"
+
+
+/*
+ * Generic helper functions
+ */
+char *mac_addr_to_str(char *buffer, bcmos_mac_address mac)
+{
+ char *fmt_str = NULL;
+
+ fmt_str = "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx";
+
+ snprintf(buffer, 20, fmt_str,
+ mac.u8[0], mac.u8[1],
+ mac.u8[2], mac.u8[3],
+ mac.u8[4], mac.u8[5]);
+
+ return buffer;
+}
+
+
+bcmos_bool mac_add_is_null(bcmos_mac_address mac)
+{
+ return ((0 != mac.u8[0]) || (0 != mac.u8[1]) || (0 != mac.u8[2]) ||
+ (0 != mac.u8[3]) || (0 != mac.u8[4]) || (0 != mac.u8[5])) ? BCMOS_FALSE : BCMOS_TRUE;
+}
+
+/**
+ * @brief Determines if string contains a valid IPv4 or IPv6 address
+ *
+ *
+ * @param ipAddrStr Pointer to string to parse
+ *
+ * @return bcmos_bool
+ * @retval TRUE String contains a valid IP address
+ * @retval FALSE String does not
+ */
+bcmos_bool BalIsValidIp(const char *ipAddrStr)
+{
+ struct sockaddr_in addr4;
+ struct in6_addr addr6;
+ bcmos_bool ret = BCMOS_FALSE;
+
+ /* Parameter checks. */
+ BUG_UNLESS(NULL != ipAddrStr, BCMOS_FALSE);
+
+ /* First look to see if it's a valid IPv4 address, then look to see if it's
+ a valid IPv6 address*/
+ if (inet_pton(AF_INET, ipAddrStr, &addr4) > 0 || inet_pton(AF_INET6, ipAddrStr, &addr6) > 0)
+ {
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+
+/**
+ * @brief Convert a string to the specified type of integer
+ *
+ * NOTE: This function uses the strtoll() function to convert the string to an
+ * integer value. U64 values greater than 0x7fffffffffffffff cannot be converted
+ * by the strtoll() function because the string value is considered out of the
+ * valid -0x8000000000000000 to 0x7fffffffffffffff 64-bit integer range.
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+static bcmos_errno BalStringToInt(char *str, BalIntStringT *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ U64 u64 = 0;
+ S64 s64 = 0;
+ char *endptr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+ BUG_UNLESS(pVal->intType > BAL_STR2INT_INVALID, BAL_PARAM);
+ BUG_UNLESS(pVal->intType < BAL_STR2INT_MAX, BAL_PARAM);
+
+ do
+ {
+ if ((pVal->intType >= BAL_STR2INT_S8) &&
+ (pVal->intType <= BAL_STR2INT_S64))
+ {
+ /* Just assume a signed 64-bit value when converting the string to
+ * an integer. Range checking is done below. Make sure that errno
+ * is set to zero before calling strtoll().
+ */
+ errno = 0;
+ pVal->intU.s64 = 0; /* Clear all possibilities to 0 */
+ s64 = strtoll(str, &endptr, 10);
+
+ /* General range and error check */
+ if ((errno == ERANGE && (s64 == LONG_MAX || s64 == LONG_MIN))
+ || (errno != 0 && s64 == 0))
+ {
+ errno = 0;
+ rc = BCM_ERR_RANGE;
+ break;
+
+ }
+
+ /* test for no digits or mixed digits and characters */
+ if (endptr == str || '\0' != *endptr)
+ {
+ errno = 0;
+ rc = BCM_ERR_PARM;
+ break;
+ }
+
+ /* routine specific range check */
+ switch (pVal->intType)
+ {
+ case BAL_STR2INT_S8:
+ if ((s64 < -128) || (s64 > 127))
+ {
+ rc = BCM_ERR_RANGE;
+ }
+ else
+ {
+ pVal->intU.s8 = (S8)s64;
+ }
+ break;
+ case BAL_STR2INT_S16:
+ if ((s64 < -32768) || (s64 > 32767))
+ {
+ rc = BCM_ERR_RANGE;
+ }
+ else
+ {
+ pVal->intU.s16 = (S16)s64;
+ }
+ break;
+ case BAL_STR2INT_S32:
+ if ((s64 < (-2147483647L -1L)) || (s64 > 2147483647L))
+ {
+ rc = BCM_ERR_RANGE;
+ }
+ else
+ {
+ pVal->intU.s32 = (S32)s64;
+ }
+ break;
+ case BAL_STR2INT_S64:
+ /* No range checking is needed since the strtoll() function
+ * does the range checking. If the string was invalid, errno
+ * would have been non-zero.
+ */
+ pVal->intU.s64 = s64;
+ break;
+ default:
+ /* Should never make it here. */
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+ else {
+ /* Just assume an unsigned 64-bit value when converting the string
+ * to an integer. Range checking is done below. Make sure that errno
+ * is set to zero before calling strtoull().
+ */
+ errno = 0;
+ pVal->intU.u64 = 0;
+ u64 = strtoull(str, &endptr, 10);
+
+ /* General range and error check */
+ if ((errno == ERANGE && (s64 == LONG_MAX || s64 == LONG_MIN))
+ || (errno != 0 && s64 == 0))
+ {
+ errno = 0;
+ rc = BCM_ERR_RANGE;
+ break;
+
+ }
+
+ /* test for no digits or mixed digits and characters */
+ if (endptr == str || '\0' != *endptr)
+ {
+ errno = 0;
+ rc = BCM_ERR_PARM;
+ break;
+ }
+
+ /* routine specific range check */
+ switch(pVal->intType)
+ {
+ case BAL_STR2INT_U8:
+ if (u64 > 255)
+ {
+ rc = BCM_ERR_RANGE;
+ }
+ else
+ {
+ pVal->intU.u8 = (U8)u64;
+ }
+ break;
+ case BAL_STR2INT_U16:
+ if (u64 > 65535)
+ {
+ rc = BCM_ERR_RANGE;
+ }
+ else
+ {
+ pVal->intU.u16 = (U16)u64;
+ }
+ break;
+ case BAL_STR2INT_U32:
+ if (u64 > 4294967295UL)
+ {
+ rc = BCM_ERR_RANGE;
+ }
+ else
+ {
+ pVal->intU.u32 = (U32)u64;
+ }
+ break;
+ case BAL_STR2INT_U64:
+ /* No range checking is needed since the strtoull() function
+ * does the range checking. If the string was invalid, errno
+ * would have been non-zero.
+ */
+ pVal->intU.u64 = u64;
+ break;
+ default:
+ /* Should never make it here. */
+ rc = BCM_ERR_PARM;
+ break;
+ }
+ }
+ } while (0);
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to an S8 type integer
+ *
+ * This function converts a string to an S8 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToS8(char *str, S8 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_S8;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.s8;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to an S16 type integer
+ *
+ * This function converts a string to an S16 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToS16(char *str, S16 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_S16;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.s16;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to an S32 type integer
+ *
+ * This function converts a string to an S32 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToS32(char *str, S32 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_S32;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.s32;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to an S64 type integer
+ *
+ * This function converts a string to an S64 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToS64(char *str, S64 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_S64;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.s64;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to a U8 type integer
+ *
+ * This function converts a string to a U8 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToU8(char *str, U8 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_U8;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.u8;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to a U16 type integer
+ *
+ * This function converts a string to a U16 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToU16(char *str, U16 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_U16;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.u16;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to a U32 type integer
+ *
+ * This function converts a string to a U32 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToU32(char *str, U32 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_U32;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.u32;
+ }
+
+ return(rc);
+}
+
+/**
+ * @brief Convert a string to a U64 type integer
+ *
+ * This function converts a string to a U64 type integer
+ *
+ * @param str String to convert
+ * @param pVal Pointer to the return value
+ *
+ * @return bcmos_errno
+ */
+bcmos_errno BalStringToU64(char *str, U64 *pVal)
+{
+ bcmos_errno rc = BAL_OK;
+ BalIntStringT intStr;
+
+ BUG_UNLESS(NULL != str, BAL_PARAM);
+ BUG_UNLESS(NULL != pVal, BAL_PARAM);
+
+ memset(&intStr, 0, sizeof(intStr));
+
+ intStr.intType = BAL_STR2INT_U64;
+
+ rc = BalStringToInt(str, &intStr);
+ if (BAL_OK == rc)
+ {
+ *pVal = intStr.intU.u64;
+ }
+
+ return(rc);
+}
+
+
+#endif /* USING_BAL_UTILS */
diff --git a/bal_release/src/lib/libutils/bal_utils.h b/bal_release/src/lib/libutils/bal_utils.h
new file mode 100644
index 0000000..78c6134
--- /dev/null
+++ b/bal_release/src/lib/libutils/bal_utils.h
@@ -0,0 +1,65 @@
+/******************************************************************************
+ *
+ * <: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.
+ *
+ * :>
+ *
+ *****************************************************************************/
+
+/**
+ * @file bal_utils.h
+ * @brief BAL Utilities include file
+ *
+ */
+
+#ifndef BALUTILS_H
+#define BALUTILS_H
+
+/*@{*/
+
+/**
+ * @brief General purpose BAL String structure.
+ *
+ * This is typically used for debugging or log messages.
+ */
+#define BAL_STRING_LENGTH 256
+
+#define MAC_STR_LEN 18
+
+/**
+ * @brief BAL String Structure
+ */
+typedef struct bal_string
+{
+ char str[BAL_STRING_LENGTH+1]; /**< The string */
+} bal_string;
+
+extern char *mac_addr_to_str(char *buffer, bcmos_mac_address mac);
+extern bcmos_bool mac_add_is_null(bcmos_mac_address mac);
+
+/*@}*/
+
+#endif /* BALUTILS_H */