BAL and Maple Release 2.2
Signed-off-by: Shad Ansari <developer@Carbon.local>
diff --git a/bcm68620_release/release/host_reference/api_proxy/Makefile b/bcm68620_release/release/host_reference/api_proxy/Makefile
new file mode 100644
index 0000000..940b839
--- /dev/null
+++ b/bcm68620_release/release/host_reference/api_proxy/Makefile
@@ -0,0 +1,12 @@
+ifeq ("$(OS)", "posix")
+ MOD_NAME = bcm_api_proxy
+ MOD_TYPE = lib
+ MOD_DEPS = transport cli
+ifeq ("$(RELEASE_BUILD)", "y")
+ MOD_DEPS += common_api
+else
+ MOD_DEPS += api
+endif
+
+ srcs = bcmolt_api_proxy.c
+endif
diff --git a/bcm68620_release/release/host_reference/api_proxy/bcmolt_api_proxy.c b/bcm68620_release/release/host_reference/api_proxy/bcmolt_api_proxy.c
new file mode 100644
index 0000000..9f71630
--- /dev/null
+++ b/bcm68620_release/release/host_reference/api_proxy/bcmolt_api_proxy.c
@@ -0,0 +1,501 @@
+/*
+<: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 <bcmtr_transport_cli.h>
+#include <bcmolt_api.h>
+#include <bcmtr_debug.h>
+#ifdef ENABLE_CLI
+#include <bcmcli.h>
+#endif
+#include "bcmolt_api_proxy.h"
+#ifdef ENABLE_LOG
+#include "bcm_dev_log.h"
+#endif
+
+/* Statistics */
+typedef struct proxy_stats
+{
+ unsigned long rx_packets;
+ unsigned long rx_bytes;
+ unsigned long tx_packets;
+ unsigned long tx_bytes;
+ unsigned long rx_errors;
+ unsigned long tx_errors;
+ unsigned long unpack_errors;
+ unsigned long pack_errors;
+ unsigned long msg_errors;
+} proxy_stats;
+
+typedef struct proxy_control_block
+{
+ bcmos_task proxy_rx_task;
+ struct sockaddr_in client;
+ uint32_t proxy_port;
+ int device_id;
+ int client_socket;
+ bcmos_bool is_running;
+ char *on_ready_cmd;
+
+ /* the maximum amount of memory that could possibly by used by all variable-sized lists within a GET request */
+#define DYNAMIC_LIST_BUFFER_SIZE (32 * 1024)
+ uint8_t dynamic_list_buffer[DYNAMIC_LIST_BUFFER_SIZE];
+
+ dev_log_id proxy_log;
+
+ proxy_stats stats;
+} proxy_control_block;
+
+/* Per device proxy control block */
+static proxy_control_block proxy_data[BCMTR_MAX_OLTS];
+static bcmos_bool is_first_proxy = BCMOS_TRUE;
+
+#ifdef ENABLE_CLI
+/*/proxy/stats command handler
+*/
+static bcmos_errno _proxy_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_packets", proxy_data[device].stats.rx_packets);
+ bcmcli_print(session, "%-16s: %lu\n", "rx_bytes", proxy_data[device].stats.rx_bytes);
+ bcmcli_print(session, "%-16s: %lu\n", "tx_packets", proxy_data[device].stats.tx_packets);
+ bcmcli_print(session, "%-16s: %lu\n", "tx_bytes", proxy_data[device].stats.tx_bytes);
+ bcmcli_print(session, "%-16s: %lu\n", "rx_errors", proxy_data[device].stats.rx_errors);
+ bcmcli_print(session, "%-16s: %lu\n", "tx_errors", proxy_data[device].stats.tx_errors);
+ bcmcli_print(session, "%-16s: %lu\n", "unpack_errors", proxy_data[device].stats.unpack_errors);
+ bcmcli_print(session, "%-16s: %lu\n", "pack_errors", proxy_data[device].stats.pack_errors);
+ bcmcli_print(session, "%-16s: %lu\n", "msg_errors", proxy_data[device].stats.msg_errors);
+ memset(&proxy_data[device].stats, 0, sizeof(proxy_stats));
+
+ return BCM_ERR_OK;
+}
+#endif /* #ifdef ENABLE_CLI */
+
+static bcmos_errno _proxy_msg_error(bcmolt_devid device, bcmolt_msg *proxy_msg)
+{
+ proxy_control_block *proxy = &proxy_data[device];
+ ++proxy->stats.msg_errors;
+ bcmolt_msg_err(proxy_msg, proxy->proxy_log, BCM_ERR_PARM, BCMOLT_ERR_FIELD_NONE, "Message is insane");
+ proxy_msg->dir = BCMOLT_MSG_DIR_RESPONSE;
+ return BCM_ERR_PARM;
+}
+
+static void _proxy_invoke(bcmolt_devid device, bcmolt_msg *proxy_msg)
+{
+ proxy_control_block *proxy = &proxy_data[device];
+ bcmos_errno rc;
+ bcmolt_system_mode system_mode;
+
+ /* Check that the message targets an object that is compatible with our system mode */
+ bcmolt_system_mode_get(device, &system_mode);
+ if (system_mode != BCMOLT_SYSTEM_MODE__NUM_OF && !bcmolt_object_is_supported(system_mode, proxy_msg->obj_type))
+ {
+ ++proxy->stats.msg_errors;
+ proxy_msg->dir = BCMOLT_MSG_DIR_RESPONSE;
+ bcmolt_msg_err(
+ proxy_msg,
+ proxy->proxy_log,
+ BCM_ERR_NOT_SUPPORTED,
+ BCMOLT_ERR_FIELD_NONE,
+ "Object type is not supported in this system mode");
+ return;
+ }
+
+ /* Invoke API */
+ switch (proxy_msg->group)
+ {
+ case BCMOLT_MGT_GROUP_CFG:
+ if ((proxy_msg->type & BCMOLT_MSG_TYPE_CLEAR) != 0)
+ {
+ rc = bcmolt_cfg_clear(device, (bcmolt_cfg *)proxy_msg);
+ }
+ else if ((proxy_msg->type & BCMOLT_MSG_TYPE_GET) != 0)
+ {
+ if ((proxy_msg->type & BCMOLT_MSG_TYPE_MULTI) != 0)
+ {
+ if (proxy_msg->msg_set == NULL)
+ {
+ rc = _proxy_msg_error(device, proxy_msg);
+ }
+ else
+ {
+ rc = bcmolt_cfg_get_multi(device,
+ (bcmolt_cfg *)proxy_msg,
+ proxy_msg->msg_set->filter_flags,
+ proxy_msg->msg_set);
+ }
+ }
+ else
+ {
+ rc = bcmolt_cfg_get(device, (bcmolt_cfg *)proxy_msg);
+ }
+ }
+ else if ((proxy_msg->type & BCMOLT_MSG_TYPE_SET) != 0)
+ {
+ rc = bcmolt_cfg_set(device, (bcmolt_cfg *)proxy_msg);
+ }
+ else
+ {
+ rc = _proxy_msg_error(device, proxy_msg);
+ }
+ break;
+
+ case BCMOLT_MGT_GROUP_STAT:
+ {
+ bcmolt_stat_flags flags;
+
+ flags = ((proxy_msg->type & BCMOLT_MSG_TYPE_CLEAR) != 0) ?
+ BCMOLT_STAT_FLAGS_CLEAR_ON_READ : 0;
+
+ rc = bcmolt_stat_get(device, (bcmolt_stat *)proxy_msg, flags);
+ }
+ break;
+
+ case BCMOLT_MGT_GROUP_OPER:
+ rc = bcmolt_oper_submit(device, (bcmolt_oper *)proxy_msg);
+ break;
+
+ case BCMOLT_MGT_GROUP_PROXY:
+ rc = bcmolt_proxy_send(device, (bcmolt_proxy *)proxy_msg);
+ break;
+
+ case BCMOLT_MGT_GROUP_STAT_CFG:
+ if ((proxy_msg->type & BCMOLT_MSG_TYPE_GET) != 0)
+ {
+ rc = bcmolt_stat_cfg_get(device, (bcmolt_stat_cfg *)proxy_msg);
+ }
+ else if ((proxy_msg->type & BCMOLT_MSG_TYPE_SET) != 0)
+ {
+ rc = bcmolt_stat_cfg_set(device, (bcmolt_stat_cfg *)proxy_msg);
+ }
+ else
+ {
+ rc = _proxy_msg_error(device, proxy_msg);
+ }
+ break;
+
+ case BCMOLT_MGT_GROUP_AUTO_CFG:
+ if ((proxy_msg->type & BCMOLT_MSG_TYPE_GET) != 0)
+ {
+ rc = bcmolt_auto_cfg_get(device, (bcmolt_auto_cfg *)proxy_msg);
+ }
+ else if ((proxy_msg->type & BCMOLT_MSG_TYPE_SET) != 0)
+ {
+ rc = bcmolt_auto_cfg_set(device, (bcmolt_auto_cfg *)proxy_msg);
+ }
+ else
+ {
+ rc = _proxy_msg_error(device, proxy_msg);
+ }
+ break;
+
+ default:
+ rc = _proxy_msg_error(device, proxy_msg);
+ }
+
+ proxy_msg->err = rc;
+}
+
+/* Pack and send message */
+static void _proxy_send(bcmolt_devid device, bcmolt_msg *msg)
+{
+ bcmtr_hdr hdr = {};
+ int32_t packed_length;
+ bcmolt_buf txb = {};
+ int len;
+
+ /* Allocate buffer and pack */
+ packed_length = bcmolt_msg_get_packed_length(msg);
+ if (packed_length <= 0)
+ {
+ ++proxy_data[device].stats.pack_errors;
+ goto done;
+ }
+ packed_length += BCMTR_HDR_SIZE;
+ if (bcmolt_buf_alloc(&txb, packed_length, BCMOLT_BUF_ENDIAN_FIXED) != BCM_ERR_OK)
+ {
+ ++proxy_data[device].stats.pack_errors;
+ goto done;
+ }
+ bcmtr_header_fill(msg, &hdr);
+ bcmtr_header_pack(&hdr, txb.start);
+ bcmolt_buf_skip(&txb, BCMTR_HDR_SIZE);
+ if (bcmolt_msg_pack(msg, &txb) != BCM_ERR_OK)
+ {
+ ++proxy_data[device].stats.pack_errors;
+ goto done;
+ }
+
+ /* Send to client */
+ len = sendto(proxy_data[device].client_socket, txb.start, bcmolt_buf_get_used(&txb), 0,
+ (struct sockaddr *)&proxy_data[device].client, sizeof(proxy_data[device].client));
+ if (len <= 0)
+ {
+ ++proxy_data[device].stats.tx_errors;
+ }
+ else
+ {
+ ++proxy_data[device].stats.tx_packets;
+ proxy_data[device].stats.tx_bytes += len;
+ }
+
+done:
+ bcmolt_buf_free(&txb);
+ return;
+}
+
+/* Task that waits for messages from Maple.
+ * Once message is received, it is forwarded to remote application
+ * via UDP socket.
+ */
+static int _proxy_rx_handler(long data)
+{
+ bcmolt_devid device = (bcmolt_devid)data;
+ bcmos_task *self = bcmos_task_current();
+ proxy_control_block *proxy = &proxy_data[device];
+ struct sockaddr_in sender;
+ socklen_t sendsize = sizeof(sender);
+ uint8_t client_buffer[BCMTR_MAX_MTU_SIZE + 128];
+ bcmolt_msg *proxy_msg;
+ bcmtr_hdr tr_hdr;
+ bcmolt_buf rxb;
+ int len;
+ uint16_t corr_tag;
+ bcmos_errno rc;
+
+ while (!self->destroyed)
+ {
+ memset(&sender, 0, sizeof(sender));
+ len = recvfrom(proxy->client_socket, client_buffer, sizeof(client_buffer), 0,
+ (struct sockaddr *)&sender, &sendsize);
+ if (len < BCMTR_HDR_SIZE)
+ {
+ ++proxy->stats.rx_errors;
+ bcmos_usleep(1000000);
+ continue;
+ }
+ ++proxy->stats.rx_packets;
+ proxy->stats.rx_bytes += len;
+
+ if (proxy->client.sin_addr.s_addr != sender.sin_addr.s_addr ||
+ proxy->client.sin_port != sender.sin_port)
+ {
+#ifdef ENABLE_LOG
+ int client_ip = ntohl(sender.sin_addr.s_addr);
+ int client_port = ntohs(sender.sin_port);
+ BCM_LOG(INFO, proxy->proxy_log, "bcm_api_proxy: device %i connected to %d.%d.%d.%d:%d\n",
+ (int)device,
+ (client_ip >> 24) & 0xff, (client_ip >> 16) & 0xff,
+ (client_ip >> 8) & 0xff, client_ip & 0xff, client_port);
+#endif
+ proxy->client = sender;
+ }
+
+ /* Unpack received message */
+ bcmolt_buf_init(&rxb, len, client_buffer, BCMOLT_BUF_ENDIAN_FIXED);
+ bcmtr_header_unpack(client_buffer, &tr_hdr);
+
+ /* Skip registration messages for now. The proxy has already registered for everything */
+ if (tr_hdr.auto_proxy_reg || tr_hdr.auto_proxy_unreg)
+ continue;
+
+ bcmolt_buf_skip(&rxb, BCMTR_HDR_SIZE);
+ proxy_msg = NULL;
+ rc = bcmolt_msg_unpack(&rxb, &proxy_msg);
+ if (rc)
+ {
+ /* Unpack error. Nothing much we can do */
+ ++proxy->stats.unpack_errors;
+ continue;
+ }
+
+ /* Store correlation tag for later */
+ proxy_msg->corr_tag = tr_hdr.corr_tag;
+ corr_tag = proxy_msg->corr_tag;
+
+ /* Point the message unpacker to local storage for dynamically-sized lists */
+ proxy_msg->list_buf = proxy->dynamic_list_buffer;
+ proxy_msg->list_buf_size = DYNAMIC_LIST_BUFFER_SIZE;
+
+ /* Invoke API */
+ _proxy_invoke(device, proxy_msg);
+
+ /* Pack and send back to the client */
+ proxy_msg->corr_tag = corr_tag;
+ _proxy_send(device, proxy_msg);
+ bcmolt_msg_free(proxy_msg);
+ }
+
+ self->destroyed = BCMOS_TRUE;
+ return 0;
+}
+
+/* Auto / proxy message handler */
+void bcmolt_api_proxy_auto_rx_cb(bcmolt_devid device, bcmolt_msg *msg)
+{
+ if (device >= BCMTR_MAX_OLTS)
+ return;
+
+ if (proxy_data[device].is_running)
+ {
+ if (proxy_data[device].on_ready_cmd &&
+ msg->obj_type == BCMOLT_OBJ_ID_DEVICE &&
+ msg->group == BCMOLT_MGT_GROUP_AUTO &&
+ msg->subgroup == BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE)
+ {
+ char on_ready_cmd[512];
+ int rc;
+ snprintf(on_ready_cmd, sizeof(on_ready_cmd) - 1, "%s %d", proxy_data[device].on_ready_cmd, (int)device);
+ rc = system(on_ready_cmd);
+#ifdef ENABLE_LOG
+ BCM_LOG(INFO, proxy_data[device].proxy_log, "Executed command %s. rc=%d\n", on_ready_cmd, rc);
+#else
+ (void)rc;
+#endif
+ }
+ _proxy_send(device, msg);
+ }
+}
+
+static bcmos_errno _proxy_start(bcmolt_devid device, uint32_t udp_port, char *on_ready)
+{
+ bcmos_errno rc;
+ bcmos_task_parm proxy_rx_parm =
+ {
+ .name = "proxy_rx",
+ .handler = _proxy_rx_handler,
+ .priority = TASK_PRIORITY_TRANSPORT_PROXY,
+ .data = device
+ };
+ struct sockaddr_in sa = {};
+
+ proxy_data[device].proxy_port = udp_port;
+ proxy_data[device].device_id = device;
+ proxy_data[device].on_ready_cmd = on_ready;
+
+ /* Start listening on proxy port */
+ proxy_data[device].client_socket = socket(AF_INET, SOCK_DGRAM, 0);
+ if (proxy_data[device].client_socket < 0)
+ {
+#ifdef ENABLE_LOG
+ BCM_LOG(ERROR, proxy_data[device].proxy_log, "Can't create UDP socket\n");
+#endif
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* Bind local */
+ sa.sin_family = AF_INET;
+ sa.sin_port = htons(proxy_data[device].proxy_port);
+ sa.sin_addr.s_addr = INADDR_ANY;
+ if (bind(proxy_data[device].client_socket, (struct sockaddr*)&sa, sizeof(sa) ) == -1)
+ {
+ perror("bind");
+#ifdef ENABLE_LOG
+ BCM_LOG(ERROR, proxy_data[device].proxy_log, "Can't bind UDP socket to port %u\n", proxy_data[device].proxy_port);
+#endif
+ close(proxy_data[device].client_socket);
+ return BCM_ERR_INTERNAL;
+ }
+
+ /* Create thread listening for incoming APIs */
+ rc = bcmos_task_create(&proxy_data[device].proxy_rx_task, &proxy_rx_parm);
+ BUG_ON(BCM_ERR_OK != rc);
+
+ proxy_data[device].is_running = BCMOS_TRUE;
+
+#ifdef ENABLE_LOG
+ BCM_LOG(INFO, proxy_data[device].proxy_log, "BCM68620 API proxy for device %d is listening for requests on UDP port %u\n",
+ (int)device, proxy_data[device].proxy_port);
+#endif
+
+ return BCM_ERR_OK;
+}
+
+bcmos_errno bcmolt_api_proxy_init(bcmcli_entry *root, bcmolt_devid device, uint32_t udp_port, char *on_ready)
+{
+#ifdef ENABLE_CLI
+ bcmcli_entry *dir;
+#endif
+
+ if (device >= BCMTR_MAX_OLTS)
+ return BCM_ERR_PARM;
+
+ if (proxy_data[device].is_running)
+ return BCM_ERR_ALREADY;
+
+#ifdef ENABLE_LOG
+ {
+ char log_id[32];
+ snprintf(log_id, sizeof(log_id) - 1, "proxy_%d", (int)device);
+ proxy_data[device].proxy_log = bcm_dev_log_id_register(log_id, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
+ }
+#else
+ proxy_data[device].proxy_log = DEV_LOG_INVALID_ID;
+#endif
+
+ if (is_first_proxy)
+ {
+#ifdef ENABLE_CLI
+ dir = bcmcli_dir_add(root, "proxy", "API proxy", BCMCLI_ACCESS_GUEST, NULL);
+ if (!dir)
+ {
+ BCM_LOG(ERROR, proxy_data[device].proxy_log, "Can't create proxy directory\n");
+ BUG();
+ }
+
+ BCMCLI_MAKE_CMD(dir, "stat", "Proxy statistics", _proxy_stats_cmd,
+ BCMCLI_MAKE_PARM_RANGE("device", "Device index", BCMCLI_PARM_NUMBER, BCMCLI_PARM_FLAG_OPTIONAL,
+ 0, BCMTR_MAX_OLTS-1));
+
+#endif
+ is_first_proxy = BCMOS_FALSE;
+ }
+ return _proxy_start(device, udp_port, on_ready);
+}
+
+void bcmolt_api_proxy_stop(void)
+{
+ int i;
+
+ for (i = 0; i < BCMTR_MAX_OLTS; i++)
+ {
+ if (proxy_data[i].is_running)
+ {
+ bcmos_task_destroy(&proxy_data[i].proxy_rx_task);
+ close(proxy_data[i].client_socket);
+ }
+ }
+}
+
diff --git a/bcm68620_release/release/host_reference/api_proxy/bcmolt_api_proxy.h b/bcm68620_release/release/host_reference/api_proxy/bcmolt_api_proxy.h
new file mode 100644
index 0000000..a76c25e
--- /dev/null
+++ b/bcm68620_release/release/host_reference/api_proxy/bcmolt_api_proxy.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_API_PROXY_H_
+#define _BCMOLT_API_PROXY_H_
+
+#include <bcmos_system.h>
+#include <bcmolt_msg.h>
+
+void bcmolt_api_proxy_auto_rx_cb(bcmolt_devid olt, bcmolt_msg *msg);
+
+bcmos_errno bcmolt_api_proxy_init(bcmcli_entry *root, bcmolt_devid device, uint32_t udp_port, char *on_ready_cmd);
+
+void bcmolt_api_proxy_stop(void);
+
+#endif
+
+