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