BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
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;
+}