Shad Ansari | 2f7f9be | 2017-06-07 13:34:53 -0700 | [diff] [blame^] | 1 | /*
|
| 2 | <:copyright-BRCM:2016:DUAL/GPL:standard
|
| 3 |
|
| 4 | Broadcom Proprietary and Confidential.(c) 2016 Broadcom
|
| 5 | All Rights Reserved
|
| 6 |
|
| 7 | Unless you and Broadcom execute a separate written software license
|
| 8 | agreement governing use of this software, this software is licensed
|
| 9 | to you under the terms of the GNU General Public License version 2
|
| 10 | (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
|
| 11 | with the following added to such license:
|
| 12 |
|
| 13 | As a special exception, the copyright holders of this software give
|
| 14 | you permission to link this software with independent modules, and
|
| 15 | to copy and distribute the resulting executable under terms of your
|
| 16 | choice, provided that you also meet, for each linked independent
|
| 17 | module, the terms and conditions of the license of that module.
|
| 18 | An independent module is a module which is not derived from this
|
| 19 | software. The special exception does not apply to any modifications
|
| 20 | of the software.
|
| 21 |
|
| 22 | Not withstanding the above, under no circumstances may you combine
|
| 23 | this software in any way with any other Broadcom software provided
|
| 24 | under a license other than the GPL, without Broadcom's express prior
|
| 25 | written consent.
|
| 26 |
|
| 27 | :>
|
| 28 | */
|
| 29 |
|
| 30 | #include <bcmos_system.h>
|
| 31 | #include <bcmtr_interface.h>
|
| 32 | #include <bcmtr_header.h>
|
| 33 | #include <bcmolt_api.h>
|
| 34 | #include <bcm_api_cli_helpers.h>
|
| 35 | #include <bcmtr_debug.h>
|
| 36 | #include <bcmcli_session.h>
|
| 37 | #include "bcmolt_remote_cli.h"
|
| 38 | #ifdef ENABLE_LOG
|
| 39 | #include "bcm_dev_log.h"
|
| 40 | #endif
|
| 41 |
|
| 42 | #define REMOTE_CLI_BUFFER_MAX 65635 /* Max reassembled packet plus header */
|
| 43 | #define REMOTE_CLI_MESSAGE_QUEUE_DEPTH BCMOS_MSG_POOL_DEFAULT_SIZE
|
| 44 |
|
| 45 | typedef enum
|
| 46 | {
|
| 47 | REMOTE_CLI_OPCODE_CLI_COMMAND,
|
| 48 | REMOTE_CLI_OPCODE_INDICATION,
|
| 49 | REMOTE_CLI_OPCODE_PROXY_RX
|
| 50 | } remote_cli_opcode;
|
| 51 |
|
| 52 | /* Statistics */
|
| 53 | typedef struct
|
| 54 | {
|
| 55 | unsigned long rx_requests;
|
| 56 | unsigned long tx_responses;
|
| 57 | unsigned long indications;
|
| 58 | unsigned long proxy_rxs;
|
| 59 | unsigned long unpack_errors;
|
| 60 | unsigned long pack_errors;
|
| 61 | unsigned long correlation_errors;
|
| 62 | unsigned long tx_socket_errors;
|
| 63 | unsigned long rx_socket_errors;
|
| 64 | unsigned long message_errors;
|
| 65 | } remote_cli_stats;
|
| 66 |
|
| 67 | typedef struct
|
| 68 | {
|
| 69 | bcmos_task output_task;
|
| 70 | bcmos_task socket_task;
|
| 71 | struct sockaddr_in client;
|
| 72 | uint16_t port;
|
| 73 | int client_socket;
|
| 74 | bcmos_bool is_running;
|
| 75 | dev_log_id log_id;
|
| 76 | bcmos_bool output_pending;
|
| 77 | uint8_t input_buffer[REMOTE_CLI_BUFFER_MAX];
|
| 78 | char *input_str;
|
| 79 | uint8_t output_buffer[REMOTE_CLI_BUFFER_MAX];
|
| 80 | uint16_t output_current_char;
|
| 81 | bcmos_mutex output_lock;
|
| 82 | int current_corr_tag;
|
| 83 | bcmcli_session *session;
|
| 84 | remote_cli_stats stats;
|
| 85 | } remote_cli_control_block;
|
| 86 |
|
| 87 | static remote_cli_control_block remote_cli_data[BCMTR_MAX_OLTS];
|
| 88 |
|
| 89 | static bcmos_errno remote_cli_stats_cmd(bcmcli_session *session, const bcmcli_cmd_parm parm[], uint16_t nparms)
|
| 90 | {
|
| 91 | int device = (int)parm[0].value.number;
|
| 92 |
|
| 93 | if (device >= BCMTR_MAX_OLTS)
|
| 94 | {
|
| 95 | return BCM_ERR_RANGE;
|
| 96 | }
|
| 97 |
|
| 98 | bcmcli_print(session, "%-16s: %lu\n", "rx_requests", remote_cli_data[device].stats.rx_requests);
|
| 99 | bcmcli_print(session, "%-16s: %lu\n", "tx_responses", remote_cli_data[device].stats.tx_responses);
|
| 100 | bcmcli_print(session, "%-16s: %lu\n", "indications", remote_cli_data[device].stats.indications);
|
| 101 | bcmcli_print(session, "%-16s: %lu\n", "proxy_rxs", remote_cli_data[device].stats.proxy_rxs);
|
| 102 | bcmcli_print(session, "%-16s: %lu\n", "unpack_errors", remote_cli_data[device].stats.unpack_errors);
|
| 103 | bcmcli_print(session, "%-16s: %lu\n", "pack_errors", remote_cli_data[device].stats.pack_errors);
|
| 104 | bcmcli_print(session, "%-16s: %lu\n", "tx_socket_errors", remote_cli_data[device].stats.tx_socket_errors);
|
| 105 | bcmcli_print(session, "%-16s: %lu\n", "rx_socket_errors", remote_cli_data[device].stats.rx_socket_errors);
|
| 106 | bcmcli_print(session, "%-16s: %lu\n", "message_errors", remote_cli_data[device].stats.message_errors);
|
| 107 | memset(&remote_cli_data[device].stats, 0, sizeof(remote_cli_stats));
|
| 108 |
|
| 109 | return BCM_ERR_OK;
|
| 110 | }
|
| 111 |
|
| 112 | static void send_output_packets(bcmolt_devid device, remote_cli_opcode opcode, uint16_t corr_tag)
|
| 113 | {
|
| 114 | bcmolt_buf buf = {};
|
| 115 | static uint8_t scratch_buffer[REMOTE_CLI_BUFFER_MAX];
|
| 116 | ssize_t len;
|
| 117 | bcmos_bool ok = BCMOS_TRUE;
|
| 118 |
|
| 119 | if (remote_cli_data[device].output_current_char == 0)
|
| 120 | {
|
| 121 | return;
|
| 122 | }
|
| 123 |
|
| 124 | bcmolt_buf_init(&buf, REMOTE_CLI_BUFFER_MAX, scratch_buffer, BCMOLT_BUF_ENDIAN_FIXED);
|
| 125 | ok = ok && bcmolt_buf_write_u8(&buf, (uint8_t)opcode);
|
| 126 | ok = ok && bcmolt_buf_write_u16_be(&buf, corr_tag);
|
| 127 | ok = ok && bcmolt_buf_write(
|
| 128 | &buf,
|
| 129 | remote_cli_data[device].output_buffer,
|
| 130 | remote_cli_data[device].output_current_char);
|
| 131 |
|
| 132 | if (!ok)
|
| 133 | {
|
| 134 | ++remote_cli_data[device].stats.pack_errors;
|
| 135 | return;
|
| 136 | }
|
| 137 |
|
| 138 | /* Send to client */
|
| 139 | len = sendto(
|
| 140 | remote_cli_data[device].client_socket,
|
| 141 | buf.start,
|
| 142 | bcmolt_buf_get_used(&buf),
|
| 143 | 0,
|
| 144 | (struct sockaddr *)&remote_cli_data[device].client,
|
| 145 | sizeof(remote_cli_data[device].client));
|
| 146 |
|
| 147 | if (len <= 0)
|
| 148 | {
|
| 149 | ++remote_cli_data[device].stats.tx_socket_errors;
|
| 150 | }
|
| 151 | }
|
| 152 |
|
| 153 | static void process_cli_input(bcmolt_devid device)
|
| 154 | {
|
| 155 | bcmos_mutex_lock(&remote_cli_data[device].output_lock);
|
| 156 | remote_cli_data[device].output_current_char = 0;
|
| 157 | memset(remote_cli_data[device].output_buffer, 0, sizeof(remote_cli_data[device].output_buffer));
|
| 158 | bcmcli_parse(remote_cli_data[device].session, remote_cli_data[device].input_str);
|
| 159 | bcmos_mutex_unlock(&remote_cli_data[device].output_lock);
|
| 160 | }
|
| 161 |
|
| 162 | static int remote_cli_session_write_cb(bcmcli_session *session, const char *buf, uint32_t size)
|
| 163 | {
|
| 164 | int i;
|
| 165 | bcmolt_devid device = *((bcmolt_devid *)bcmcli_session_user_priv(session));
|
| 166 |
|
| 167 | bcmos_mutex_lock(&remote_cli_data[device].output_lock);
|
| 168 | for (i = 0; i < size; ++i)
|
| 169 | {
|
| 170 | remote_cli_data[device].output_buffer[remote_cli_data[device].output_current_char] = buf[i];
|
| 171 | ++remote_cli_data[device].output_current_char;
|
| 172 | }
|
| 173 | bcmos_mutex_unlock(&remote_cli_data[device].output_lock);
|
| 174 |
|
| 175 | return size;
|
| 176 | }
|
| 177 |
|
| 178 | static bcmos_errno remote_cli_open_session(bcmolt_devid device)
|
| 179 | {
|
| 180 | bcmos_errno rc;
|
| 181 | bcmcli_session_parm sess_parm = {};
|
| 182 | sess_parm.access_right = BCMCLI_ACCESS_DEBUG;
|
| 183 | sess_parm.write = remote_cli_session_write_cb;
|
| 184 | sess_parm.user_priv = bcmos_calloc(sizeof(device));
|
| 185 | sess_parm.line_edit_mode = BCMCLI_LINE_EDIT_DISABLE;
|
| 186 | BUG_ON(sess_parm.user_priv == NULL);
|
| 187 | *((bcmolt_devid *)sess_parm.user_priv) = device;
|
| 188 | rc = bcmcli_session_open(&sess_parm, &remote_cli_data[device].session);
|
| 189 |
|
| 190 | if (rc != BCM_ERR_OK)
|
| 191 | {
|
| 192 | perror("Can't open session");
|
| 193 | #ifdef ENABLE_LOG
|
| 194 | BCM_LOG(
|
| 195 | ERROR,
|
| 196 | remote_cli_data[device].log_id,
|
| 197 | "Can't open session\n");
|
| 198 | #endif
|
| 199 | shutdown(remote_cli_data[device].client_socket, SHUT_RDWR);
|
| 200 | }
|
| 201 | return rc;
|
| 202 | }
|
| 203 |
|
| 204 | static bcmos_errno remote_cli_open_socket(bcmolt_devid device)
|
| 205 | {
|
| 206 | struct sockaddr_in sa = {};
|
| 207 | /* Start listening on port */
|
| 208 | remote_cli_data[device].client_socket = socket(AF_INET, SOCK_DGRAM, 0);
|
| 209 | if (remote_cli_data[device].client_socket < 0)
|
| 210 | {
|
| 211 | perror("Can't create socket");
|
| 212 | #ifdef ENABLE_LOG
|
| 213 | BCM_LOG(
|
| 214 | ERROR,
|
| 215 | remote_cli_data[device].log_id,
|
| 216 | "Can't create socket\n");
|
| 217 | #endif
|
| 218 | return BCM_ERR_INTERNAL;
|
| 219 | }
|
| 220 |
|
| 221 | /* Bind local */
|
| 222 | sa.sin_family = AF_INET;
|
| 223 | sa.sin_port = (in_port_t)htons(remote_cli_data[device].port);
|
| 224 | sa.sin_addr.s_addr = INADDR_ANY;
|
| 225 | if (bind(remote_cli_data[device].client_socket, (struct sockaddr*)&sa, sizeof(sa)) == -1)
|
| 226 | {
|
| 227 | perror("Can't bind to socket");
|
| 228 | #ifdef ENABLE_LOG
|
| 229 | BCM_LOG(
|
| 230 | ERROR,
|
| 231 | remote_cli_data[device].log_id,
|
| 232 | "Can't bind socket to port %u\n",
|
| 233 | remote_cli_data[device].port);
|
| 234 | #endif
|
| 235 | shutdown(remote_cli_data[device].client_socket, SHUT_RDWR);
|
| 236 | return BCM_ERR_INTERNAL;
|
| 237 | }
|
| 238 | return BCM_ERR_OK;
|
| 239 | }
|
| 240 |
|
| 241 | static void remote_cli_indication_cb(bcmos_module_id module_id, bcmos_msg *msg)
|
| 242 | {
|
| 243 | bcmolt_devid device = (bcmolt_devid)(module_id - BCMOS_MODULE_ID_REMOTE_CLI_DEV0);
|
| 244 | bcmolt_msg *ind = msg->data;
|
| 245 |
|
| 246 | bcmos_mutex_lock(&remote_cli_data[device].output_lock);
|
| 247 | remote_cli_data[device].output_current_char = 0;
|
| 248 | memset(remote_cli_data[device].output_buffer, 0, sizeof(remote_cli_data[device].output_buffer));
|
| 249 |
|
| 250 | apicli_msg_dump(remote_cli_data[device].session, ind);
|
| 251 | if (ind->group == BCMOLT_MGT_GROUP_AUTO)
|
| 252 | {
|
| 253 | send_output_packets(device, REMOTE_CLI_OPCODE_INDICATION, ind->corr_tag);
|
| 254 | ++remote_cli_data[device].stats.indications;
|
| 255 | }
|
| 256 | else if (ind->group == BCMOLT_MGT_GROUP_PROXY_RX)
|
| 257 | {
|
| 258 | send_output_packets(device, REMOTE_CLI_OPCODE_PROXY_RX, ind->corr_tag);
|
| 259 | ++remote_cli_data[device].stats.proxy_rxs;
|
| 260 | }
|
| 261 | else
|
| 262 | {
|
| 263 | #ifdef ENABLE_LOG
|
| 264 | BCM_LOG(
|
| 265 | ERROR,
|
| 266 | remote_cli_data[device].log_id,
|
| 267 | "Unknown group type %u\n",
|
| 268 | ind->group);
|
| 269 | #endif
|
| 270 | }
|
| 271 | bcmos_mutex_unlock(&remote_cli_data[device].output_lock);
|
| 272 |
|
| 273 | bcmolt_msg_free(ind);
|
| 274 | }
|
| 275 |
|
| 276 | static void remote_cli_output_cb(bcmos_module_id module_id, bcmos_msg *msg)
|
| 277 | {
|
| 278 | bcmolt_devid device = (bcmolt_devid)(module_id - BCMOS_MODULE_ID_REMOTE_CLI_DEV0);
|
| 279 | process_cli_input(device);
|
| 280 | send_output_packets(device, REMOTE_CLI_OPCODE_CLI_COMMAND, remote_cli_data[device].current_corr_tag);
|
| 281 | remote_cli_data[device].output_pending = BCMOS_FALSE;
|
| 282 | ++remote_cli_data[device].stats.tx_responses;
|
| 283 | }
|
| 284 |
|
| 285 | static int remote_cli_socket_task(long data)
|
| 286 | {
|
| 287 | bcmolt_devid device = (bcmolt_devid)data;
|
| 288 | struct sockaddr_in sender;
|
| 289 | socklen_t sendsize = sizeof(sender);
|
| 290 | bcmolt_buf buf;
|
| 291 | ssize_t len;
|
| 292 | uint8_t opcode = 0;
|
| 293 | uint16_t corr_tag = 0;
|
| 294 | bcmos_bool ok = BCMOS_TRUE;
|
| 295 | bcmos_msg output_msg = { .handler = remote_cli_output_cb };
|
| 296 | bcmos_errno rc;
|
| 297 |
|
| 298 | rc = remote_cli_open_socket(device);
|
| 299 | BCMOS_CHECK_RETURN(rc != BCM_ERR_OK, rc, -1);
|
| 300 | rc = remote_cli_open_session(device);
|
| 301 | BCMOS_CHECK_RETURN(rc != BCM_ERR_OK, rc, -1);
|
| 302 |
|
| 303 | while (remote_cli_data[device].is_running)
|
| 304 | {
|
| 305 | if (remote_cli_data[device].output_pending)
|
| 306 | {
|
| 307 | bcmos_usleep(1000);
|
| 308 | continue;
|
| 309 | }
|
| 310 |
|
| 311 | remote_cli_data[device].current_corr_tag = -1;
|
| 312 | memset(remote_cli_data[device].input_buffer, 0, sizeof(remote_cli_data[device].input_buffer));
|
| 313 |
|
| 314 | memset(&sender, 0, sizeof(sender));
|
| 315 | len = recvfrom(
|
| 316 | remote_cli_data[device].client_socket,
|
| 317 | remote_cli_data[device].input_buffer,
|
| 318 | sizeof(remote_cli_data[device].input_buffer),
|
| 319 | 0,
|
| 320 | (struct sockaddr *)&sender,
|
| 321 | &sendsize);
|
| 322 | if (len < 0)
|
| 323 | {
|
| 324 | bcmos_usleep(1000000);
|
| 325 | continue;
|
| 326 | }
|
| 327 | ++remote_cli_data[device].stats.rx_requests;
|
| 328 |
|
| 329 | if ((remote_cli_data[device].client.sin_addr.s_addr != sender.sin_addr.s_addr) ||
|
| 330 | (remote_cli_data[device].client.sin_port != sender.sin_port))
|
| 331 | {
|
| 332 | remote_cli_data[device].client = sender;
|
| 333 | }
|
| 334 |
|
| 335 | /* Unpack received message */
|
| 336 | bcmolt_buf_init(&buf, (uint32_t)len, remote_cli_data[device].input_buffer, BCMOLT_BUF_ENDIAN_FIXED);
|
| 337 | ok = ok && bcmolt_buf_read_u8(&buf, &opcode);
|
| 338 | ok = ok && bcmolt_buf_read_u16_be(&buf, &corr_tag);
|
| 339 |
|
| 340 | if (!ok)
|
| 341 | {
|
| 342 | ++remote_cli_data[device].stats.unpack_errors;
|
| 343 | continue;
|
| 344 | }
|
| 345 |
|
| 346 | if ((remote_cli_opcode)opcode != REMOTE_CLI_OPCODE_CLI_COMMAND)
|
| 347 | {
|
| 348 | ++remote_cli_data[device].stats.unpack_errors;
|
| 349 | continue;
|
| 350 | }
|
| 351 |
|
| 352 | if ((remote_cli_data[device].current_corr_tag != corr_tag) && (remote_cli_data[device].current_corr_tag >= 0))
|
| 353 | {
|
| 354 | ++remote_cli_data[device].stats.correlation_errors;
|
| 355 | continue;
|
| 356 | }
|
| 357 |
|
| 358 | remote_cli_data[device].input_str = (char *)bcmolt_buf_snap_get(&buf);
|
| 359 | remote_cli_data[device].input_str[bcmolt_buf_get_remaining_size(&buf)] = '\0';
|
| 360 | remote_cli_data[device].current_corr_tag = corr_tag;
|
| 361 | remote_cli_data[device].output_pending = BCMOS_TRUE;
|
| 362 | rc = bcmos_msg_send_to_module(
|
| 363 | bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, device),
|
| 364 | &output_msg,
|
| 365 | BCMOS_MSG_SEND_AUTO_FREE);
|
| 366 | if (rc != BCM_ERR_OK)
|
| 367 | {
|
| 368 | ++remote_cli_data[device].stats.message_errors;
|
| 369 | }
|
| 370 | }
|
| 371 |
|
| 372 | bcmos_free(bcmcli_session_user_priv(remote_cli_data[device].session));
|
| 373 | bcmcli_session_close(remote_cli_data[device].session);
|
| 374 | shutdown(remote_cli_data[device].client_socket, SHUT_RDWR);
|
| 375 | remote_cli_data[device].socket_task.destroyed = BCMOS_TRUE;
|
| 376 | return 0;
|
| 377 | }
|
| 378 |
|
| 379 | static bcmos_errno remote_cli_start(bcmolt_devid device, uint32_t remote_cli_port)
|
| 380 | {
|
| 381 | bcmos_errno rc;
|
| 382 | bcmos_task_parm output_task_params =
|
| 383 | {
|
| 384 | .name = "remote_cli_indication",
|
| 385 | .priority = TASK_PRIORITY_TRANSPORT_REMOTE_CLI
|
| 386 | };
|
| 387 |
|
| 388 | bcmos_task_parm socket_task_params =
|
| 389 | {
|
| 390 | .name = "remote_cli_main",
|
| 391 | .handler = remote_cli_socket_task,
|
| 392 | .priority = TASK_PRIORITY_TRANSPORT_REMOTE_CLI,
|
| 393 | .data = (long)device
|
| 394 | };
|
| 395 |
|
| 396 | bcmos_module_parm module_params =
|
| 397 | {
|
| 398 | .qparm = { .name = "remote_cli", .size = REMOTE_CLI_MESSAGE_QUEUE_DEPTH }
|
| 399 | };
|
| 400 |
|
| 401 | remote_cli_data[device].port = remote_cli_port;
|
| 402 | remote_cli_data[device].current_corr_tag = -1;
|
| 403 | remote_cli_data[device].is_running = BCMOS_TRUE;
|
| 404 |
|
| 405 | /* Create thread listening for incoming APIs */
|
| 406 | rc = bcmos_task_create(&remote_cli_data[device].socket_task, &socket_task_params);
|
| 407 | BUG_ON(BCM_ERR_OK != rc);
|
| 408 | rc = bcmos_task_create(&remote_cli_data[device].output_task, &output_task_params);
|
| 409 | BUG_ON(BCM_ERR_OK != rc);
|
| 410 | bcmos_mutex_create(&remote_cli_data[device].output_lock, 0, "remote_cli");
|
| 411 |
|
| 412 | rc = bcmos_module_create(
|
| 413 | bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, device),
|
| 414 | &remote_cli_data[device].output_task,
|
| 415 | &module_params);
|
| 416 | BUG_ON(BCM_ERR_OK != rc);
|
| 417 |
|
| 418 | #ifdef ENABLE_LOG
|
| 419 | BCM_LOG(
|
| 420 | INFO,
|
| 421 | remote_cli_data[device].log_id,
|
| 422 | "BCM68620 remote cli for device %d is listening on port %u\n",
|
| 423 | (int)device,
|
| 424 | remote_cli_data[device].port);
|
| 425 | #endif
|
| 426 |
|
| 427 | return BCM_ERR_OK;
|
| 428 | }
|
| 429 |
|
| 430 | /* Auto / proxy message handler */
|
| 431 | void bcmolt_remote_cli_auto_rx_cb(bcmolt_devid device, bcmolt_msg *msg)
|
| 432 | {
|
| 433 | bcmos_errno err;
|
| 434 | bcmolt_msg *ind_clone = NULL;
|
| 435 |
|
| 436 | if (device >= BCMTR_MAX_OLTS)
|
| 437 | {
|
| 438 | return;
|
| 439 | }
|
| 440 |
|
| 441 | if (remote_cli_data[device].is_running)
|
| 442 | {
|
| 443 | err = bcmolt_msg_clone(&ind_clone, msg);
|
| 444 | if (err != BCM_ERR_OK)
|
| 445 | {
|
| 446 | #ifdef ENABLE_LOG
|
| 447 | BCM_LOG(ERROR, remote_cli_data[device].log_id, "Indication clone failed: %s\n", bcmos_strerror(err));
|
| 448 | #endif
|
| 449 | return;
|
| 450 | }
|
| 451 |
|
| 452 | ind_clone->os_msg.handler = remote_cli_indication_cb;
|
| 453 | ind_clone->os_msg.data = ind_clone;
|
| 454 | err = bcmos_msg_send_to_module(
|
| 455 | bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, device),
|
| 456 | &ind_clone->os_msg,
|
| 457 | 0);
|
| 458 | if (err != BCM_ERR_OK)
|
| 459 | {
|
| 460 | ++remote_cli_data[device].stats.message_errors;
|
| 461 | }
|
| 462 | }
|
| 463 | }
|
| 464 |
|
| 465 | bcmos_errno bcmolt_remote_cli_init(bcmcli_entry *root, bcmolt_devid device, uint32_t remote_cli_port)
|
| 466 | {
|
| 467 | bcmcli_entry *dir;
|
| 468 | if (device >= BCMTR_MAX_OLTS)
|
| 469 | {
|
| 470 | return BCM_ERR_PARM;
|
| 471 | }
|
| 472 |
|
| 473 | if (remote_cli_data[device].is_running)
|
| 474 | {
|
| 475 | return BCM_ERR_ALREADY;
|
| 476 | }
|
| 477 |
|
| 478 | BCM_MEMZERO_STRUCT(&remote_cli_data[device]);
|
| 479 |
|
| 480 | #ifdef ENABLE_LOG
|
| 481 | {
|
| 482 | char log_id[32];
|
| 483 | snprintf(log_id, sizeof(log_id) - 1, "remote_cli_%d", (int)device);
|
| 484 | remote_cli_data[device].log_id =
|
| 485 | bcm_dev_log_id_register(log_id, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
|
| 486 | }
|
| 487 | #else
|
| 488 | remote_cli_data[device].log_id = DEV_LOG_INVALID_ID;
|
| 489 | #endif
|
| 490 |
|
| 491 | dir = bcmcli_dir_add(root, "remote_cli", "Remote CLI", BCMCLI_ACCESS_GUEST, NULL);
|
| 492 | if (!dir)
|
| 493 | {
|
| 494 | #ifdef ENABLE_LOG
|
| 495 | BCM_LOG(ERROR, remote_cli_data[device].log_id, "Can't create remote CLI directory\n");
|
| 496 | #endif
|
| 497 | BUG();
|
| 498 | }
|
| 499 |
|
| 500 | BCMCLI_MAKE_CMD(dir, "stat", "Remote CLI statistics", remote_cli_stats_cmd,
|
| 501 | BCMCLI_MAKE_PARM_RANGE(
|
| 502 | "device",
|
| 503 | "Device index",
|
| 504 | BCMCLI_PARM_NUMBER,
|
| 505 | BCMCLI_PARM_FLAG_OPTIONAL,
|
| 506 | 0,
|
| 507 | BCMTR_MAX_OLTS - 1));
|
| 508 |
|
| 509 | return remote_cli_start(device, remote_cli_port);
|
| 510 | }
|
| 511 |
|
| 512 | void bcmolt_remote_cli_stop(void)
|
| 513 | {
|
| 514 | int i;
|
| 515 | bcmos_bool was_running[BCMTR_MAX_OLTS] = {};
|
| 516 |
|
| 517 | for (i = 0; i < BCMTR_MAX_OLTS; i++)
|
| 518 | {
|
| 519 | was_running[i] = remote_cli_data[i].is_running;
|
| 520 | if (was_running[i])
|
| 521 | {
|
| 522 | shutdown(remote_cli_data[i].client_socket, SHUT_RDWR);
|
| 523 | remote_cli_data[i].is_running = BCMOS_FALSE;
|
| 524 | }
|
| 525 | }
|
| 526 |
|
| 527 | for (i = 0; i < BCMTR_MAX_OLTS; i++)
|
| 528 | {
|
| 529 | if (!was_running[i])
|
| 530 | {
|
| 531 | continue;
|
| 532 | }
|
| 533 | while (!remote_cli_data[i].socket_task.destroyed)
|
| 534 | {
|
| 535 | bcmos_usleep(10000);
|
| 536 | }
|
| 537 | bcmos_task_destroy(&remote_cli_data[i].socket_task);
|
| 538 | bcmos_module_destroy(bcmos_module_id_for_device(BCMOS_MODULE_ID_REMOTE_CLI_DEV0, (bcmolt_devid)i));
|
| 539 | bcmos_task_destroy(&remote_cli_data[i].output_task);
|
| 540 | bcmos_mutex_destroy(&remote_cli_data[i].output_lock);
|
| 541 | }
|
| 542 | }
|
| 543 |
|