BAL and Maple Release 2.2

Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_reference/remote_cli/Makefile b/bcm68620_release/release/host_reference/remote_cli/Makefile
new file mode 100644
index 0000000..ee2fe6e
--- /dev/null
+++ b/bcm68620_release/release/host_reference/remote_cli/Makefile
@@ -0,0 +1,9 @@
+ifeq ("$(OS)", "posix")

+ifeq ("$(ENABLE_CLI)", "y")

+    MOD_NAME = bcm_remote_cli

+    MOD_TYPE = lib

+    MOD_DEPS = cli api_cli

+    srcs = bcmolt_remote_cli.c

+    USE_LINT = yes

+endif

+endif

diff --git a/bcm68620_release/release/host_reference/remote_cli/bcmolt_remote_cli.c b/bcm68620_release/release/host_reference/remote_cli/bcmolt_remote_cli.c
new file mode 100644
index 0000000..9ca9d2e
--- /dev/null
+++ b/bcm68620_release/release/host_reference/remote_cli/bcmolt_remote_cli.c
@@ -0,0 +1,543 @@
+/*

+<: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 <bcmtr_interface.h>

+#include <bcmtr_header.h>

+#include <bcmolt_api.h>

+#include <bcm_api_cli_helpers.h>

+#include <bcmtr_debug.h>

+#include <bcmcli_session.h>

+#include "bcmolt_remote_cli.h"

+#ifdef ENABLE_LOG

+#include "bcm_dev_log.h"

+#endif

+

+#define REMOTE_CLI_BUFFER_MAX 65635 /* Max reassembled packet plus header */

+#define REMOTE_CLI_MESSAGE_QUEUE_DEPTH BCMOS_MSG_POOL_DEFAULT_SIZE

+

+typedef enum

+{

+    REMOTE_CLI_OPCODE_CLI_COMMAND,

+    REMOTE_CLI_OPCODE_INDICATION,

+    REMOTE_CLI_OPCODE_PROXY_RX

+} remote_cli_opcode;

+

+/* Statistics */

+typedef struct

+{

+    unsigned long rx_requests;

+    unsigned long tx_responses;

+    unsigned long indications;

+    unsigned long proxy_rxs;

+    unsigned long unpack_errors;

+    unsigned long pack_errors;

+    unsigned long correlation_errors;

+    unsigned long tx_socket_errors;

+    unsigned long rx_socket_errors;

+    unsigned long message_errors;

+} remote_cli_stats;

+

+typedef struct

+{

+    bcmos_task output_task;

+    bcmos_task socket_task;

+    struct sockaddr_in client;

+    uint16_t port;

+    int client_socket;

+    bcmos_bool is_running;

+    dev_log_id log_id;

+    bcmos_bool output_pending;

+    uint8_t input_buffer[REMOTE_CLI_BUFFER_MAX];

+    char *input_str;

+    uint8_t output_buffer[REMOTE_CLI_BUFFER_MAX];

+    uint16_t output_current_char;

+    bcmos_mutex output_lock;

+    int current_corr_tag;

+    bcmcli_session *session;

+    remote_cli_stats stats;

+} remote_cli_control_block;

+

+static remote_cli_control_block remote_cli_data[BCMTR_MAX_OLTS];

+

+static bcmos_errno remote_cli_stats_cmd(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)

+{

+    int device = (int)parm[0].value.number;

+

+    if (device >= BCMTR_MAX_OLTS)

+    {

+        return BCM_ERR_RANGE;

+    }

+

+    bcmcli_print(session, "%-16s: %lu\n", "rx_requests", remote_cli_data[device].stats.rx_requests);

+    bcmcli_print(session, "%-16s: %lu\n", "tx_responses", remote_cli_data[device].stats.tx_responses);

+    bcmcli_print(session, "%-16s: %lu\n", "indications", remote_cli_data[device].stats.indications);

+    bcmcli_print(session, "%-16s: %lu\n", "proxy_rxs", remote_cli_data[device].stats.proxy_rxs);

+    bcmcli_print(session, "%-16s: %lu\n", "unpack_errors", remote_cli_data[device].stats.unpack_errors);

+    bcmcli_print(session, "%-16s: %lu\n", "pack_errors", remote_cli_data[device].stats.pack_errors);

+    bcmcli_print(session, "%-16s: %lu\n", "tx_socket_errors", remote_cli_data[device].stats.tx_socket_errors);

+    bcmcli_print(session, "%-16s: %lu\n", "rx_socket_errors", remote_cli_data[device].stats.rx_socket_errors);

+    bcmcli_print(session, "%-16s: %lu\n", "message_errors", remote_cli_data[device].stats.message_errors);

+    memset(&remote_cli_data[device].stats, 0, sizeof(remote_cli_stats));

+

+    return BCM_ERR_OK;

+}

+

+static void send_output_packets(bcmolt_devid device, remote_cli_opcode opcode, uint16_t corr_tag)

+{

+    bcmolt_buf buf = {};

+    static uint8_t scratch_buffer[REMOTE_CLI_BUFFER_MAX];

+    ssize_t len;

+    bcmos_bool ok = BCMOS_TRUE;

+

+    if (remote_cli_data[device].output_current_char == 0)

+    {

+        return;

+    }

+

+    bcmolt_buf_init(&buf, REMOTE_CLI_BUFFER_MAX, scratch_buffer, BCMOLT_BUF_ENDIAN_FIXED);

+    ok = ok && bcmolt_buf_write_u8(&buf, (uint8_t)opcode);

+    ok = ok && bcmolt_buf_write_u16_be(&buf, corr_tag);

+    ok = ok && bcmolt_buf_write(

+        &buf,

+        remote_cli_data[device].output_buffer,

+        remote_cli_data[device].output_current_char);

+

+    if (!ok)

+    {

+        ++remote_cli_data[device].stats.pack_errors;

+        return;

+    }

+

+    /* Send to client */

+    len = sendto(

+        remote_cli_data[device].client_socket,

+        buf.start,

+        bcmolt_buf_get_used(&buf),

+        0,

+        (struct sockaddr *)&remote_cli_data[device].client,

+        sizeof(remote_cli_data[device].client));

+

+    if (len <= 0)

+    {

+        ++remote_cli_data[device].stats.tx_socket_errors;

+    }

+}

+

+static void process_cli_input(bcmolt_devid device)

+{

+    bcmos_mutex_lock(&remote_cli_data[device].output_lock);

+    remote_cli_data[device].output_current_char = 0;

+    memset(remote_cli_data[device].output_buffer, 0, sizeof(remote_cli_data[device].output_buffer));

+    bcmcli_parse(remote_cli_data[device].session, remote_cli_data[device].input_str);

+    bcmos_mutex_unlock(&remote_cli_data[device].output_lock);

+}

+

+static int remote_cli_session_write_cb(bcmcli_session *session, const char *buf, uint32_t size)

+{

+    int i;

+    bcmolt_devid device = *((bcmolt_devid *)bcmcli_session_user_priv(session));

+

+    bcmos_mutex_lock(&remote_cli_data[device].output_lock);

+    for (i = 0; i < size; ++i)

+    {

+        remote_cli_data[device].output_buffer[remote_cli_data[device].output_current_char] = buf[i];

+        ++remote_cli_data[device].output_current_char;

+    }

+    bcmos_mutex_unlock(&remote_cli_data[device].output_lock);

+

+    return size;

+}

+

+static bcmos_errno remote_cli_open_session(bcmolt_devid device)

+{

+    bcmos_errno rc;

+    bcmcli_session_parm sess_parm = {};

+    sess_parm.access_right = BCMCLI_ACCESS_DEBUG;

+    sess_parm.write = remote_cli_session_write_cb;

+    sess_parm.user_priv = bcmos_calloc(sizeof(device));

+    sess_parm.line_edit_mode = BCMCLI_LINE_EDIT_DISABLE;

+    BUG_ON(sess_parm.user_priv == NULL);

+    *((bcmolt_devid *)sess_parm.user_priv) = device;

+    rc = bcmcli_session_open(&sess_parm, &remote_cli_data[device].session);

+

+    if (rc != BCM_ERR_OK)

+    {

+        perror("Can't open session");

+#ifdef ENABLE_LOG

+        BCM_LOG(

+            ERROR,

+            remote_cli_data[device].log_id,

+            "Can't open session\n");

+#endif

+        shutdown(remote_cli_data[device].client_socket, SHUT_RDWR);

+    }

+    return rc;

+}

+

+static bcmos_errno remote_cli_open_socket(bcmolt_devid device)

+{

+    struct sockaddr_in sa = {};

+    /* Start listening on port */

+    remote_cli_data[device].client_socket = socket(AF_INET, SOCK_DGRAM, 0);

+    if (remote_cli_data[device].client_socket < 0)

+    {

+        perror("Can't create socket");

+#ifdef ENABLE_LOG

+        BCM_LOG(

+            ERROR,

+            remote_cli_data[device].log_id,

+            "Can't create socket\n");

+#endif

+        return BCM_ERR_INTERNAL;

+    }

+

+    /* Bind local */

+    sa.sin_family = AF_INET;

+    sa.sin_port = (in_port_t)htons(remote_cli_data[device].port);

+    sa.sin_addr.s_addr = INADDR_ANY;

+    if (bind(remote_cli_data[device].client_socket, (struct sockaddr*)&sa, sizeof(sa)) == -1)

+    {

+        perror("Can't bind to socket");

+#ifdef ENABLE_LOG

+        BCM_LOG(

+            ERROR,

+            remote_cli_data[device].log_id,

+            "Can't bind socket to port %u\n",

+            remote_cli_data[device].port);

+#endif

+        shutdown(remote_cli_data[device].client_socket, SHUT_RDWR);

+        return BCM_ERR_INTERNAL;

+    }

+    return BCM_ERR_OK;

+}

+

+static void remote_cli_indication_cb(bcmos_module_id module_id, bcmos_msg *msg)

+{

+    bcmolt_devid device = (bcmolt_devid)(module_id - BCMOS_MODULE_ID_REMOTE_CLI_DEV0);

+    bcmolt_msg *ind = msg->data;

+

+    bcmos_mutex_lock(&remote_cli_data[device].output_lock);

+    remote_cli_data[device].output_current_char = 0;

+    memset(remote_cli_data[device].output_buffer, 0, sizeof(remote_cli_data[device].output_buffer));

+

+    apicli_msg_dump(remote_cli_data[device].session, ind);

+    if (ind->group == BCMOLT_MGT_GROUP_AUTO)

+    {

+        send_output_packets(device, REMOTE_CLI_OPCODE_INDICATION, ind->corr_tag);

+        ++remote_cli_data[device].stats.indications;

+    }

+    else if (ind->group == BCMOLT_MGT_GROUP_PROXY_RX)

+    {

+        send_output_packets(device, REMOTE_CLI_OPCODE_PROXY_RX, ind->corr_tag);

+        ++remote_cli_data[device].stats.proxy_rxs;

+    }

+    else

+    {

+#ifdef ENABLE_LOG

+        BCM_LOG(

+            ERROR,

+            remote_cli_data[device].log_id,

+            "Unknown group type %u\n",

+            ind->group);

+#endif

+    }

+    bcmos_mutex_unlock(&remote_cli_data[device].output_lock);

+

+    bcmolt_msg_free(ind);

+}

+

+static void remote_cli_output_cb(bcmos_module_id module_id, bcmos_msg *msg)

+{

+    bcmolt_devid device = (bcmolt_devid)(module_id - BCMOS_MODULE_ID_REMOTE_CLI_DEV0);

+    process_cli_input(device);

+    send_output_packets(device, REMOTE_CLI_OPCODE_CLI_COMMAND, remote_cli_data[device].current_corr_tag);

+    remote_cli_data[device].output_pending = BCMOS_FALSE;

+    ++remote_cli_data[device].stats.tx_responses;

+}

+

+static int remote_cli_socket_task(long data)

+{

+    bcmolt_devid device = (bcmolt_devid)data;

+    struct sockaddr_in sender;

+    socklen_t sendsize = sizeof(sender);

+    bcmolt_buf buf;

+    ssize_t len;

+    uint8_t opcode = 0;

+    uint16_t corr_tag = 0;

+    bcmos_bool ok = BCMOS_TRUE;

+    bcmos_msg output_msg = { .handler = remote_cli_output_cb };

+    bcmos_errno rc;

+

+    rc = remote_cli_open_socket(device);

+    BCMOS_CHECK_RETURN(rc != BCM_ERR_OK, rc, -1);

+    rc = remote_cli_open_session(device);

+    BCMOS_CHECK_RETURN(rc != BCM_ERR_OK, rc, -1);

+

+    while (remote_cli_data[device].is_running)

+    {

+        if (remote_cli_data[device].output_pending)

+        {

+            bcmos_usleep(1000);

+            continue;

+        }

+

+        remote_cli_data[device].current_corr_tag = -1;

+        memset(remote_cli_data[device].input_buffer, 0, sizeof(remote_cli_data[device].input_buffer));

+

+        memset(&sender, 0, sizeof(sender));

+        len = recvfrom(

+            remote_cli_data[device].client_socket,

+            remote_cli_data[device].input_buffer,

+            sizeof(remote_cli_data[device].input_buffer),

+            0,

+            (struct sockaddr *)&sender,

+            &sendsize);

+        if (len < 0)

+        {

+            bcmos_usleep(1000000);

+            continue;

+        }

+        ++remote_cli_data[device].stats.rx_requests;

+

+        if ((remote_cli_data[device].client.sin_addr.s_addr != sender.sin_addr.s_addr) ||

+            (remote_cli_data[device].client.sin_port != sender.sin_port))

+        {

+            remote_cli_data[device].client = sender;

+        }

+

+        /* Unpack received message */

+        bcmolt_buf_init(&buf, (uint32_t)len, remote_cli_data[device].input_buffer, BCMOLT_BUF_ENDIAN_FIXED);

+        ok = ok && bcmolt_buf_read_u8(&buf, &opcode);

+        ok = ok && bcmolt_buf_read_u16_be(&buf, &corr_tag);

+

+        if (!ok)

+        {

+            ++remote_cli_data[device].stats.unpack_errors;

+            continue;

+        }

+

+        if ((remote_cli_opcode)opcode != REMOTE_CLI_OPCODE_CLI_COMMAND)

+        {

+            ++remote_cli_data[device].stats.unpack_errors;

+            continue;

+        }

+

+        if ((remote_cli_data[device].current_corr_tag != corr_tag) && (remote_cli_data[device].current_corr_tag >= 0))

+        {

+            ++remote_cli_data[device].stats.correlation_errors;

+            continue;

+        }

+

+        remote_cli_data[device].input_str = (char *)bcmolt_buf_snap_get(&buf);

+        remote_cli_data[device].input_str[bcmolt_buf_get_remaining_size(&buf)] = '\0';

+        remote_cli_data[device].current_corr_tag = corr_tag;

+        remote_cli_data[device].output_pending = BCMOS_TRUE;

+        rc = bcmos_msg_send_to_module(

+            bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, device),

+            &output_msg,

+            BCMOS_MSG_SEND_AUTO_FREE);

+        if (rc != BCM_ERR_OK)

+        {

+            ++remote_cli_data[device].stats.message_errors;

+        }

+    }

+

+    bcmos_free(bcmcli_session_user_priv(remote_cli_data[device].session));

+    bcmcli_session_close(remote_cli_data[device].session);

+    shutdown(remote_cli_data[device].client_socket, SHUT_RDWR);

+    remote_cli_data[device].socket_task.destroyed = BCMOS_TRUE;

+    return 0;

+}

+

+static bcmos_errno remote_cli_start(bcmolt_devid device, uint32_t remote_cli_port)

+{

+    bcmos_errno rc;

+    bcmos_task_parm output_task_params =

+    {

+        .name = "remote_cli_indication",

+        .priority = TASK_PRIORITY_TRANSPORT_REMOTE_CLI

+    };

+

+    bcmos_task_parm socket_task_params =

+    {

+        .name = "remote_cli_main",

+        .handler = remote_cli_socket_task,

+        .priority = TASK_PRIORITY_TRANSPORT_REMOTE_CLI,

+        .data = (long)device

+    };

+

+    bcmos_module_parm module_params =

+    {

+        .qparm = { .name = "remote_cli", .size = REMOTE_CLI_MESSAGE_QUEUE_DEPTH }

+    };

+

+    remote_cli_data[device].port = remote_cli_port;

+    remote_cli_data[device].current_corr_tag = -1;

+    remote_cli_data[device].is_running = BCMOS_TRUE;

+

+    /* Create thread listening for incoming APIs */

+    rc = bcmos_task_create(&remote_cli_data[device].socket_task, &socket_task_params);

+    BUG_ON(BCM_ERR_OK != rc);

+    rc = bcmos_task_create(&remote_cli_data[device].output_task, &output_task_params);

+    BUG_ON(BCM_ERR_OK != rc);

+    bcmos_mutex_create(&remote_cli_data[device].output_lock, 0, "remote_cli");

+

+    rc = bcmos_module_create(

+        bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, device),

+        &remote_cli_data[device].output_task,

+        &module_params);

+    BUG_ON(BCM_ERR_OK != rc);

+

+#ifdef ENABLE_LOG

+    BCM_LOG(

+        INFO,

+        remote_cli_data[device].log_id,

+        "BCM68620 remote cli for device %d is listening on port %u\n",

+        (int)device,

+        remote_cli_data[device].port);

+#endif

+

+    return BCM_ERR_OK;

+}

+

+/* Auto / proxy message handler */

+void bcmolt_remote_cli_auto_rx_cb(bcmolt_devid device, bcmolt_msg *msg)

+{

+    bcmos_errno err;

+    bcmolt_msg *ind_clone = NULL;

+

+    if (device >= BCMTR_MAX_OLTS)

+    {

+        return;

+    }

+

+    if (remote_cli_data[device].is_running)

+    {

+        err = bcmolt_msg_clone(&ind_clone, msg);

+        if (err != BCM_ERR_OK)

+        {

+#ifdef ENABLE_LOG

+            BCM_LOG(ERROR, remote_cli_data[device].log_id, "Indication clone failed: %s\n", bcmos_strerror(err));

+#endif

+            return;

+        }

+

+        ind_clone->os_msg.handler = remote_cli_indication_cb;

+        ind_clone->os_msg.data = ind_clone;

+        err = bcmos_msg_send_to_module(

+            bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, device),

+            &ind_clone->os_msg,

+            0);

+        if (err != BCM_ERR_OK)

+        {

+            ++remote_cli_data[device].stats.message_errors;

+        }

+    }

+}

+

+bcmos_errno bcmolt_remote_cli_init(bcmcli_entry *root, bcmolt_devid device, uint32_t remote_cli_port)

+{

+    bcmcli_entry *dir;

+    if (device >= BCMTR_MAX_OLTS)

+    {

+        return BCM_ERR_PARM;

+    }

+

+    if (remote_cli_data[device].is_running)

+    {

+        return BCM_ERR_ALREADY;

+    }

+

+    BCM_MEMZERO_STRUCT(&remote_cli_data[device]);

+

+#ifdef ENABLE_LOG

+    {

+    char log_id[32];

+    snprintf(log_id, sizeof(log_id) - 1, "remote_cli_%d", (int)device);

+    remote_cli_data[device].log_id =

+        bcm_dev_log_id_register(log_id, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);

+    }

+#else

+    remote_cli_data[device].log_id = DEV_LOG_INVALID_ID;

+#endif

+

+    dir = bcmcli_dir_add(root, "remote_cli", "Remote CLI", BCMCLI_ACCESS_GUEST, NULL);

+    if (!dir)

+    {

+#ifdef ENABLE_LOG

+        BCM_LOG(ERROR, remote_cli_data[device].log_id, "Can't create remote CLI directory\n");

+#endif

+        BUG();

+    }

+

+    BCMCLI_MAKE_CMD(dir, "stat", "Remote CLI statistics", remote_cli_stats_cmd,

+        BCMCLI_MAKE_PARM_RANGE(

+            "device",

+            "Device index",

+            BCMCLI_PARM_NUMBER,

+            BCMCLI_PARM_FLAG_OPTIONAL,

+            0,

+            BCMTR_MAX_OLTS - 1));

+

+    return remote_cli_start(device, remote_cli_port);

+}

+

+void bcmolt_remote_cli_stop(void)

+{

+    int i;

+    bcmos_bool was_running[BCMTR_MAX_OLTS] = {};

+

+    for (i = 0; i < BCMTR_MAX_OLTS; i++)

+    {

+        was_running[i] = remote_cli_data[i].is_running;

+        if (was_running[i])

+        {

+            shutdown(remote_cli_data[i].client_socket, SHUT_RDWR);

+            remote_cli_data[i].is_running = BCMOS_FALSE;

+        }

+    }

+

+    for (i = 0; i < BCMTR_MAX_OLTS; i++)

+    {

+        if (!was_running[i])

+        {

+            continue;

+        }

+        while (!remote_cli_data[i].socket_task.destroyed)

+        {

+            bcmos_usleep(10000);

+        }

+        bcmos_task_destroy(&remote_cli_data[i].socket_task);

+        bcmos_module_destroy(bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, (bcmolt_devid)i));

+        bcmos_task_destroy(&remote_cli_data[i].output_task);

+        bcmos_mutex_destroy(&remote_cli_data[i].output_lock);

+    }

+}

+

diff --git a/bcm68620_release/release/host_reference/remote_cli/bcmolt_remote_cli.h b/bcm68620_release/release/host_reference/remote_cli/bcmolt_remote_cli.h
new file mode 100644
index 0000000..e20a64b
--- /dev/null
+++ b/bcm68620_release/release/host_reference/remote_cli/bcmolt_remote_cli.h
@@ -0,0 +1,44 @@
+/*

+<: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 _BCMOLT_REMOTE_CLI_H_

+#define _BCMOLT_REMOTE_CLI_H_

+

+#include <bcmos_system.h>

+#include <bcmolt_msg.h>

+

+void bcmolt_remote_cli_auto_rx_cb(bcmolt_devid olt, bcmolt_msg *msg);

+

+bcmos_errno bcmolt_remote_cli_init(bcmcli_entry *root, bcmolt_devid device, uint32_t remote_cli_port);

+

+void bcmolt_remote_cli_stop(void);

+

+#endif

+

+