blob: fcc1573b8b257db3c66627434f323c85b4a5aa1b [file] [log] [blame]
Shad Ansari2f7f9be2017-06-07 13:34:53 -07001/******************************************************************************
2 *
3 * <:copyright-BRCM:2016:DUAL/GPL:standard
4 *
5 * Copyright (c) 2016 Broadcom
6 * All Rights Reserved
7 *
8 * Unless you and Broadcom execute a separate written software license
9 * agreement governing use of this software, this software is licensed
10 * to you under the terms of the GNU General Public License version 2
11 * (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
12 * with the following added to such license:
13 *
14 * As a special exception, the copyright holders of this software give
15 * you permission to link this software with independent modules, and
16 * to copy and distribute the resulting executable under terms of your
17 * choice, provided that you also meet, for each linked independent
18 * module, the terms and conditions of the license of that module.
19 * An independent module is a module which is not derived from this
20 * software. The special exception does not apply to any modifications
21 * of the software.
22 *
23 * Not withstanding the above, under no circumstances may you combine
24 * this software in any way with any other Broadcom software provided
25 * under a license other than the GPL, without Broadcom's express prior
26 * written consent.
27 *
28 * :>
29 *
30 *****************************************************************************/
31
32/**
33 * @file bal_core.c
34 * @brief The code that comprises the main entry point and initialization
35 * code for the BAL Core.
36 *
37 * @addtogroup ctrlr
38 */
39
40/*@{*/
41
42#include <bcmos_system.h>
43#include <bcmcli.h>
44#include <bal_switch_util.h>
45#include <bal_mac_util.h>
46#include <bal_version.h>
47#include <cmdline.h>
48#include <bal_core.h>
49#include <bal_cli.h>
50
51#include "rsc_mgr.h"
52#include "bal_worker.h"
53#include "bal_switch_acc_term.h"
54
55#ifdef ENABLE_LOG
56#include <bcm_dev_log.h>
57#endif
58
59#ifdef OMCI_SVC
60#include <omci_svc.h>
61#endif
62
63#if defined(CONFIG_MAC_RPC)
64#define CONFIG_MAC_UTIL_IP_PORT
65#endif
66
67#ifdef ENABLE_LOG
68/*
69 * @brief The Logging device id for the BAL core
70 */
71dev_log_id log_id_core;
72#endif
73
74
75/*--- local function declarations ---*/
76static void welcome_to_bal(void);
77static bcmos_errno bal_core_init(void);
78static void bal_core_finish(void);
79static void bal_parse_config(struct bcmbal_config_params *p_params);
80static bcmos_errno bal_rpc_soc_gen(void);
81
82/*
83 * Worker thread and RX thread(s) data structures
84 */
85static bcmos_task core_worker_thread;
86
87static bcmos_errno _usage(const char *cmd);
88
89#define BAL_CHECK_IP_ARGUMENT(_i, _argc, _option) \
90 do { \
91 if (_i == _argc - 1) \
92 { \
93 printf("Error: IP:port is expected after %s option\n", _option); \
94 return _usage(argv[0]);\
95 }\
96 } while (0)
97
98
99#define CORE_MGMT_IP_PORT_CMDLINE_OPT "-C"
100#define BAL_API_IP_PORT_CMDLINE_OPT "-A"
101#define BAL_MAC_IP_PORT_CMDLINE_OPT "-M"
102#define BAL_SW_IP_CMDLINE_OPT "-S"
103#define BAL_INIT_SCRIPT_OPT "-f"
104#define BAL_LOG_FILE_OPT "-F"
105#define BAL_HELP_OPT "-h"
106#define BAL_LONG_HELP_OPT "--help"
107#define BAL_LEVEL_OPT "-L"
108#define BAL_NO_LOG_OPT "-nl"
109#define BAL_LOG_SYSLOG_OPT "-syslog"
110#define BAL_NO_LINEEDIT_OPT "-ne"
111
112
113/* Command line arguments */
114static cl_argument supported_cl_args[] =
115{
116#ifdef CONFIG_MAC_UTIL_IP_PORT
117 { .short_name = BAL_MAC_IP_PORT_CMDLINE_OPT,
118 .extra_arg = "mac_device_ip:port",
119 .description = "IP address:UDP port where the MAC device listens for RPC messages",
120 .flags = CL_ARGUMENT_FLAG_MANDATORY,
121 .owner = "BAL"
122 },
123#endif
124#ifdef CONFIG_SWITCH_RPC
125 { .short_name = BAL_SW_IP_CMDLINE_OPT,
126 .extra_arg = "switch_ip",
127 .description = "Switch IP address for RPC messages",
128 .flags = CL_ARGUMENT_FLAG_MANDATORY,
129 },
130#endif
131 { .short_name = CORE_MGMT_IP_PORT_CMDLINE_OPT,
132 .extra_arg = "core_mgmt_ip:port",
133 .description = "IP address:UDP port where the core listens for messages from the BAL Public API",
134 },
135 { .short_name = BAL_API_IP_PORT_CMDLINE_OPT,
136 .extra_arg = "al_api_mgmt ip:port",
137 .description = "IP address:UDP port where BAL Public API listens for responses from the core",
138 },
139 { .short_name = BAL_LEVEL_OPT,
140 .extra_arg = "level",
141 .description = "CLI level: guest | admin | debug",
142 },
143 { .short_name = BAL_NO_LINEEDIT_OPT,
144 .description = "Disable line editing",
145 },
146 { .short_name = BAL_INIT_SCRIPT_OPT,
147 .extra_arg = "script_file_name",
148 .description = "Script containing BAL CLI commands",
149 },
150#ifdef ENABLE_LOG
151 { .short_name = BAL_LOG_FILE_OPT,
152 .extra_arg = "log_file_name",
153 .description = "Log into file",
154 },
155 { .long_name = BAL_LOG_SYSLOG_OPT,
156 .description = "Log to syslog",
157 },
158 { .short_name = BAL_NO_LOG_OPT,
159 .description = "Disable logger",
160 },
161#endif
162#ifndef BUILD_OF_AGENT
163 { .short_name = BAL_HELP_OPT,
164 .long_name = BAL_LONG_HELP_OPT,
165 .description = "This help",
166 },
167#endif
168};
169
170/*
171 * The BAL core config file definitions
172 */
173
174#define TOPOLOGY_FILE_NAME "bal_topology.ini"
175#define CONFIG_FILE_NAME "bal_config.ini"
176#define MAX_CONFIG_FILE_LINE_LEN 256
177#define MAX_CONFIG_PARAM_NAME_LEN 64
178#define MAX_CONFIG_PARAM_VALUE_LEN 64
179
180bcmbal_config_params bal_config_params =
181{
182 .iwf_mode = BCMBAL_IWF_MODE_PER_FLOW,
183 .intf_maptable = 2,
184 .num_nni_ports = BCM_TOPO_MAX_NNI_PORTS,
185 /* The interface mapping table default value is set in the switch utilities */
186 .topo_params.pon_mode = BCM_TOPO_PON_MODE_INVALID,
187 /* Default CLI session parameters */
188 .access = BCMCLI_ACCESS_ADMIN,
189 .edit_mode = BCMCLI_LINE_EDIT_DEFAULT,
190};
191static bcmos_bool bal_initialized;
192
193#define RPC_SOC_TEMPLATE_FILE_NAME "rpc.soc.template"
194#define RPC_SOC_FILE_NAME "rpc.soc"
195#define MAX_CMD_LINE_LEN 256
196
197 /*
198 * An enumeration of the possible iwf modes
199 */
200static bcmcli_enum_val iwf_mode_enum[] = {
201 { .name="direct", .val=BCMBAL_IWF_MODE_DIRECT_MAPPING},
202 { .name="per_flow", .val=BCMBAL_IWF_MODE_PER_FLOW},
203 BCMCLI_ENUM_LAST
204};
205
206/**
207 * @brief The Broadcom Ltd logo.
208 */
209static const char *g_p_company_logo =
210"\n\n"
211" *\n"
212" * *\n"
213" * *\n"
214" * *\n"
215" * *\n"
216" * *\n"
217" * *\n"
218" * * * * * *\n"
219" * * * *\n\n"
220"Copyright (c) 2017 Broadcom Ltd\n\n";
221
222
223#ifdef ENABLE_LOG
224/* Create log_id for the core */
225static void bal_core_log_init(void)
226{
227 /* Register the core logging context */
228 log_id_core = bcm_dev_log_id_register("CORE_CTRLR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH);
229 BUG_ON(log_id_core == DEV_LOG_INVALID_ID);
230
231 bcm_dev_log_level_set_style(DEV_LOG_LEVEL_FATAL, BCM_DEV_LOG_STYLE_BOLD);
232 bcm_dev_log_level_set_style(DEV_LOG_LEVEL_ERROR, BCM_DEV_LOG_STYLE_BOLD);
233
234 BCM_LOG(DEBUG, log_id_core, "BAL Core is starting\n");
235}
236
237/* Initialize logger */
238static int bal_dev_log_time_to_str_cb(uint32_t bal_time, char *time_str, int time_str_size)
239{
240 /* Round timestamp to the nearest ms */
241 uint32_t time_ms = (bal_time + 500) / 1000;
242 return snprintf(time_str, time_str_size, "%05u.%03u", time_ms / 1000, time_ms % 1000);
243}
244#endif
245
246/*****************************************************************************/
247/**
248 * @brief A function to initialize the system logging subsystem
249 *
250 * This function is executed at system startup time
251 *
252 *****************************************************************************/
253bcmos_errno bcmbal_log_init(void)
254{
255 bcmos_errno ret = BCM_ERR_OK;
256
257#ifdef ENABLE_LOG
258 const char *log_file_name = bal_config_params.log_file_name;
259 if (bal_config_params.disable_log)
260 return BCM_ERR_OK;
261 do
262 {
263 if (NULL == log_file_name && !bal_config_params.log_syslog)
264 {
265#define DEV_LOG_SIZE1 1<<20
266#define DEV_LOG_QUEUE_SIZE 1000
267 static uint8_t logger_buf1[DEV_LOG_SIZE1];
268 void *addresses[DEV_LOG_MAX_FILES] = {logger_buf1};
269 uint32_t sizes[DEV_LOG_MAX_FILES] = {sizeof(logger_buf1)};
270 uint32_t flags[DEV_LOG_MAX_FILES] = {BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND};
271 /* Initialize the system logger for the core threads */
272 ret = bcm_dev_log_init_default_logger(addresses,
273 sizes,
274 flags,
275 BCM_SIZEOFARRAY(addresses),
276 0x4000,
277 TASK_PRIORITY_DEV_LOG,
278 DEV_LOG_QUEUE_SIZE);
279 }
280 else
281 {
282 bcm_dev_log_parm dev_log_parm = {};
283 int nfiles = 0;
284 if (NULL != log_file_name)
285 {
286 dev_log_parm.log_file[nfiles].type = BCM_DEV_LOG_FILE_REGULAR;
287 dev_log_parm.log_file[nfiles].udef_parms = (char *)(long)log_file_name;
288 dev_log_parm.log_file[nfiles].flags = BCM_DEV_LOG_FILE_FLAG_VALID;
289 ++nfiles;
290 };
291 if (bal_config_params.log_syslog)
292 {
293 dev_log_parm.log_file[nfiles].type = BCM_DEV_LOG_FILE_SYSLOG;
294 dev_log_parm.log_file[nfiles].udef_parms = "BAL";
295 dev_log_parm.log_file[nfiles].flags = BCM_DEV_LOG_FILE_FLAG_VALID;
296 ++nfiles;
297 };
298 ret = bcm_dev_log_init_default_logger_ext(&dev_log_parm,
299 nfiles, /* Log into file and/or syslog */
300 0x4000,
301 TASK_PRIORITY_DEV_LOG,
302 DEV_LOG_QUEUE_SIZE);
303 }
304
305 if(BCM_ERR_OK != ret)
306 {
307 printf("Error initializing logger default values (%s)\n", bcmos_strerror(ret));
308 break;
309 }
310
311 bcm_dev_log_set_time_to_str_cb(bal_dev_log_time_to_str_cb);
312 }
313 while(0);
314#endif /* #ifdef ENABLE_LOG */
315
316 return ret;
317}
318
319
320/* Parse command line parameters */
321bcmos_errno bcmbal_cmdline_parse(int argc, char *argv[])
322{
323 int i;
324
325 if (cl_validate(argc, argv, supported_cl_args, BCM_SIZEOFARRAY(supported_cl_args)) != BCM_ERR_OK)
326 return _usage(argv[0]);
327
328 /*
329 * Parse all optional arguments
330 */
331 for (i = 1; i < argc; i++)
332 {
333 if (!strcmp(argv[i], CORE_MGMT_IP_PORT_CMDLINE_OPT))
334 {
335 BAL_CHECK_IP_ARGUMENT(i, argc, CORE_MGMT_IP_PORT_CMDLINE_OPT);
336 bal_config_params.core_mgmt_ip_port = argv[++i];
337 }
338 else if (!strcmp(argv[i], BAL_API_IP_PORT_CMDLINE_OPT))
339 {
340 BAL_CHECK_IP_ARGUMENT(i, argc, BAL_API_IP_PORT_CMDLINE_OPT);
341 bal_config_params.balapi_mgmt_ip_port = argv[++i];
342 }
343#ifdef CONFIG_MAC_UTIL_IP_PORT
344 else if (!strcmp(argv[i], BAL_MAC_IP_PORT_CMDLINE_OPT))
345 {
346 /* When we build for x86, this is a necessary argument, because the MAC device is
347 * remote from the BAL core. When we build for WRX, this argument isn't required
348 * because the MAC device is local and the mac_rpc_ip_port value is not used.
349 */
350 BAL_CHECK_IP_ARGUMENT(i, argc, BAL_MAC_IP_PORT_CMDLINE_OPT);
351 bal_config_params.mac_rpc_ip_port = argv[++i];
352 }
353#endif
354#ifdef CONFIG_SWITCH_RPC
355 else if (!strcmp(argv[i], BAL_SW_IP_CMDLINE_OPT))
356 {
357 BAL_CHECK_IP_ARGUMENT(i, argc, BAL_SW_IP_CMDLINE_OPT);
358 bal_config_params.sw_rpc_ip = argv[++i];
359 }
360#endif
361 else if (!strcmp(argv[i], BAL_LEVEL_OPT))
362 {
363 ++i;
364 if (!strcmp(argv[i], "admin"))
365 bal_config_params.access = BCMCLI_ACCESS_ADMIN;
366 else if (!strcmp(argv[i], "guest"))
367 bal_config_params.access = BCMCLI_ACCESS_GUEST;
368 else if (!strcmp(argv[i], "debug"))
369 bal_config_params.access = BCMCLI_ACCESS_DEBUG;
370 else
371 return _usage(argv[0]);
372 }
373 else if (!strcmp(argv[i], BAL_NO_LINEEDIT_OPT))
374 {
375 bal_config_params.edit_mode = BCMCLI_LINE_EDIT_DISABLE;
376 }
377#ifdef ENABLE_LOG
378 else if (!strcmp(argv[i], BAL_NO_LOG_OPT))
379 {
380 bal_config_params.disable_log = BCMOS_TRUE;
381 }
382 else if (!strcmp(argv[i], BAL_LOG_SYSLOG_OPT))
383 {
384 bal_config_params.log_syslog = BCMOS_TRUE;
385 }
386 else if (!strcmp(argv[i], BAL_LOG_FILE_OPT))
387 {
388 if (i == argc - 1)
389 {
390 bcmos_printf("Log file name is expected after %s option\n", BAL_LOG_FILE_OPT);
391 return _usage(argv[0]);
392 }
393 bal_config_params.log_file_name = argv[++i];
394 }
395#endif
396 else if (!strcmp(argv[i], BAL_INIT_SCRIPT_OPT))
397 {
398 if (i == argc - 1)
399 {
400 bcmos_printf("Script file name is expected after %s option\n", BAL_INIT_SCRIPT_OPT);
401 return _usage(argv[0]);
402 }
403 bal_config_params.init_script = argv[++i];
404 }
405 else if (!strcmp(argv[i], BAL_HELP_OPT) || !strcmp(argv[i], BAL_LONG_HELP_OPT))
406 {
407 return _usage(argv[0]);
408 }
409 else
410 {
411 /* We have encountered a non-mandatory command line option
412 * that we don't recognize. This is a fatal error. Print
413 * the proper command line invocation.
414 */
415 printf("Error: unrecognized cmdline option specified (%s)\n", argv[i]);
416 return _usage(argv[0]);
417 }
418 }
419
420 /*
421 * The user MUST specify the mac and switch IP:port for IPC
422 */
423 if (BCMOS_FALSE
424#ifndef BAL_MONOLITHIC
425 || (NULL == bal_config_params.core_mgmt_ip_port) || (NULL == bal_config_params.balapi_mgmt_ip_port)
426#endif
427#ifdef CONFIG_MAC_UTIL_IP_PORT
428 || ((BCMOS_TRUE != bcmbal_is_mac_in_loopback()) && (NULL == bal_config_params.mac_rpc_ip_port))
429#endif
430#ifdef CONFIG_SWITCH_RPC
431 || (NULL == bal_config_params.sw_rpc_ip)
432#endif
433 )
434 {
435 printf("Error: you must enter ALL mandatory cmdline options\n");
436 return _usage(argv[0]);
437 }
438
439 return BCM_ERR_OK;
440}
441
442/* This is BAL initialization function that is called when BAL is compiled
443 * as a library rather than stand-alone application.
444 * \param[in] argc Number of command line parameters
445 * \param[in] argv Command line parameter array
446 * \returns BCM_ERR_OK (0) if successful or error<0 in case of failure
447 */
448bcmos_errno bcmbal_init(void)
449{
450 bcmos_errno ret;
451
452 /* Read the bal config file (bal_config.ini) parameters, if the config file is present */
453 bal_parse_config(&bal_config_params);
454
455 /* Now initialize the system topology */
456 ret = bcm_topo_init((bal_config_params.topo_params.num_of_devs &&
457 bal_config_params.topo_params.num_of_pons_per_dev &&
458 bal_config_params.topo_params.pon_mode != BCM_TOPO_PON_MODE_INVALID) ?
459 &bal_config_params.topo_params : NULL, TOPOLOGY_FILE_NAME);
460
461 if(BCM_ERR_OK != ret)
462 {
463 bcmos_printf("Error initializing the system topology\n");
464 return ret;
465 }
466
467#ifdef ENABLE_LOG
468 bal_core_log_init();
469#endif
470
471 /* Generate rpc.soc from rpc.soc.template */
472 if (BCM_ERR_OK != (ret = bal_rpc_soc_gen()))
473 return ret;
474
475 do
476 {
477
478 /* Initialize the BAL core itself
479 * NOTE: It is assumed that logging has been successfully
480 * initialized before this call is made
481 */
482 ret = bal_core_init();
483 if(BCM_ERR_OK != ret)
484 {
485 BCM_LOG(ERROR, log_id_core, "Error initializing the bal core\n");
486 break;
487 }
488
489 /* Initialize the switch utilities */
490 ret = sw_util_init();
491 if(BCM_ERR_OK != ret)
492 {
493 BCM_LOG(ERROR, log_id_core, "Error initializing the bal switch utilities\n");
494 break;
495 }
496
497 /* Initialize the mac utilities */
498 ret = mac_util_init(bal_config_params.mac_rpc_ip_port);
499 if(BCM_ERR_OK != ret)
500 {
501 BCM_LOG(ERROR, log_id_core, "Error initializing the bal mac utilities\n");
502 break;
503 }
504
505 /* Initialize the bal public api */
506 ret = bcmbal_api_init(bal_config_params.balapi_mgmt_ip_port, bal_config_params.core_mgmt_ip_port);
507 if(BCM_ERR_OK != ret)
508 {
509 BCM_LOG(ERROR, log_id_core, "Could not initialize the BAL Public API\n");
510 break;
511 }
512
513 bal_initialized = BCMOS_TRUE;
514
515 /* Print out the welcome banner */
516 welcome_to_bal();
517 }
518 while(0);
519
520 return ret;
521}
522
523void bcmbal_finish(void)
524{
525 bcmbal_cli_finish();
526 if (bal_initialized)
527 bal_core_finish();
528}
529
530/* Top-level init sequence */
531bcmos_errno bcmbal_init_all(int argc, char *argv[], bcmbal_exit_cb exit_cb)
532{
533 bcmos_errno err;
534 err = bcmbal_cmdline_parse(argc, argv);
535 err = (err != BCM_ERR_OK) ? err : bcmos_init();
536 err = (err != BCM_ERR_OK) ? err : bcmbal_log_init();
537 err = (err != BCM_ERR_OK) ? err : bcmbal_init();
538 err = (err != BCM_ERR_OK) ? err : bcmbal_cli_init(exit_cb);
539 return err;
540}
541
542/*****************************************************************************/
543/**
544 * @brief The BAL core command line usage function
545 *
546 * A function to display the proper bal_core command line format
547 *
548 * @param cmd A pointer to the command line string that the user entered to
549 * start the BAL core.
550 *
551 * @returns BCM_ERR_PARM - This function is always run as a result of the user
552 * entering an invalid value on the command line.
553 *
554 *****************************************************************************/
555static bcmos_errno _usage(const char *cmd)
556{
557#ifndef BUILD_OF_AGENT
558 /* For SDN_AGENT all parm usage info is printed in the agent's main */
559 cl_print_usage(cmd, NULL, supported_cl_args, BCM_SIZEOFARRAY(supported_cl_args), CL_ARGUMENT_USAGE_FLAG_NONE);
560#endif
561 return BCM_ERR_PARM;
562}
563
564/*****************************************************************************/
565/**
566 * @brief The BAL core initialization function
567 *
568 * A function to initialize the BAL core and all its associated threads.
569 *
570 * @returns BCM_ERR_OK, or the return value from first function called
571 * that fails.
572 *
573 *****************************************************************************/
574static bcmos_errno bal_core_init(void)
575{
576 bcmos_task_parm task_p = {};
577 bcmos_module_parm module_p = {};
578 bcmos_errno ret = BCM_ERR_OK;
579 mgmt_queue_addr_ports mgmt_queue_info;
580
581 do
582 {
583 /* Create message queues */
584 mgmt_queue_info.core_mgmt_ip_port = bal_config_params.core_mgmt_ip_port;
585 mgmt_queue_info.balapi_mgmt_ip_port = bal_config_params.balapi_mgmt_ip_port;
586 ret = core_msg_queue_init(&mgmt_queue_info);
587 if (BCM_ERR_OK != ret)
588 {
589 BCM_LOG(ERROR, log_id_core, "Couldn't create message queues\n");
590 break;
591 }
592
593 /* Create worker thread & modules for mgmt messages */
594 task_p.name = "core_worker";
595 task_p.priority = TASK_PRIORITY_WORKER;
596
597 ret = bcmos_task_create(&core_worker_thread, &task_p);
598 if (BCM_ERR_OK != ret)
599 {
600 BCM_LOG(ERROR, log_id_core, "Couldn't create worker thread\n");
601 break;
602 }
603
604 /*
605 * Initialize the worker thread that was just spawned
606 */
607 core_worker_thread_init();
608
609 /*
610 * Now create the module for the worker thread
611 */
612 module_p.qparm.name = "core_worker_mgmt_module";
613 module_p.init = _bal_worker_mgmt_module_init;
614 ret = bcmos_module_create(BCMOS_MODULE_ID_WORKER_MGMT, &core_worker_thread, &module_p);
615 if (ret)
616 {
617 BCM_LOG(ERROR, log_id_core, "Couldn't create mgmt worker module\n");
618 break;
619 }
620
621#ifdef CONFIG_SWITCH_RPC
622 ret = sw_util_pkt_send_init(bal_config_params.sw_rpc_ip, bal_config_params.pkt_send_svr_listen_port);
623 if (BCM_ERR_OK != ret)
624 {
625 BCM_LOG(ERROR, log_id_core, "Couldn't initialize the packet send interface ret = %d\n", ret);
626 break;
627 }
628 else
629 {
630 BCM_LOG(DEBUG, log_id_core,
631 "\"Packet send\" interface is initialized"
632 " to use server at %s:%d\n",
633 bal_config_params.sw_rpc_ip, bal_config_params.pkt_send_svr_listen_port );
634 }
635#endif
636 }
637 while(0);
638
639 return ret;
640}
641
642/*****************************************************************************/
643/**
644 * @brief The BAL core finish function
645 *
646 * A function to clean up the BAL core and all its associated threads on
647 * exit.
648 *
649 * @returns BCM_ERR_OK
650 *
651 *****************************************************************************/
652static void bal_core_finish(void)
653{
654 rsc_mgr_uninit();
655 mac_util_finish();
656 sw_util_finish();
657
658 core_worker_thread_finish();
659
660 bcmos_module_destroy(BCMOS_MODULE_ID_WORKER_MGMT);
661
662 bcmos_task_destroy(&core_worker_thread);
663
664 /* Let logger task have enough time to drain its message queue. */
665#ifdef ENABLE_LOG
666 bcmos_usleep(1000000);
667 bcm_dev_log_destroy();
668#endif
669}
670
671
672/*****************************************************************************/
673/**
674 * @brief A function to print the welcome banner for BAL
675 *
676 * This function is executed at system startup time
677 *
678 *****************************************************************************/
679static void welcome_to_bal(void)
680{
681 time_t tm = time(NULL);
682
683 /* @todo Don't print the welcome banner when running as a daemon */
684
685 printf("%s", g_p_company_logo);
686
687 BCM_LOG(INFO, log_id_core, "*** Welcome to BAL %s version %s (Built: %s)\n",
688#ifndef BUILD_OF_AGENT
689 "",
690#else
691 "OF-Agent",
692#endif
693 BAL_VERSION, BAL_BUILD_DATE);
694 BCM_LOG(INFO, log_id_core, "%s\n", BAL_BUILD_INFO);
695
696 BCM_LOG(INFO, log_id_core, "Time is: %s", asctime(localtime(&tm)));
697
698#ifdef TEST_SW_UTIL_LOOPBACK
699 BCM_LOG(INFO, log_id_core, "----BUILT WITH TEST_SW_UTIL_LOOPBACK\n");
700#endif
701
702 if (BCMOS_TRUE == bcmbal_is_mac_in_loopback())
703 {
704 BCM_LOG(INFO, log_id_core, "----CONFIGURED WITH MAC UTIL LOOPBACK\n");
705 }
706}
707
708/*****************************************************************************/
709/**
710 * @brief A trim helper function
711 *
712 * This function is used to get rid of trailing and leading whitespace
713 * including the "\n" from fgets()
714 *
715 * @param s A pointer to the string that is to be trimmed
716 *
717 * @returns -char *, the trimmed sting
718 *
719 */
720static char *trim (char * s)
721{
722 /* Initialize start, end pointers */
723 int len = strlen(s);
724 char *s1 = s, *s2 = &s[len - 1];
725
726 /* Trim and delimit right side */
727 while ( (isspace (*s2)) && (s2 >= s1) )
728 {
729 s2--;
730 len--;
731 }
732
733 *(s2+1) = '\0';
734
735 /* Trim left side */
736 while ( (isspace (*s1)) && (s1 < s2) )
737 {
738 s1++;
739 len--;
740 }
741
742 /* Copy finished string. Use memmove, as it is guaranteed to correctly handle overlapping strings. */
743 memmove (s, s1, len + 1);
744 return s;
745}
746
747/* A helper function for finding an enum array entry value, given it's name*/
748static long find_val_by_enum_name(bcmcli_enum_val *p_enum_array, const char * name)
749{
750 long val = -1;
751 int ii;
752
753
754 for(ii=0; p_enum_array[ii].name != NULL; ii++)
755 {
756 if(0 == strcmp(name, p_enum_array[ii].name))
757 {
758 val = p_enum_array[ii].val;
759 }
760 }
761
762 return val;
763}
764
765/*****************************************************************************/
766/**
767 * @brief A function that reads bal config file
768 *
769 * This function is used to read the bal config file into the
770 * bcmbal_config_params structure.
771 *
772 * The config file is defined to be named "bal_config.ini" and is
773 * of the format:
774 * param_name=param_value
775 *
776 * @param p_params A pointer to the core configuration parameters
777 *
778 * @returns void
779 *
780 */
781static void bal_parse_config(bcmbal_config_params *p_params)
782{
783 char *s, buff[MAX_CONFIG_FILE_LINE_LEN];
784 char name[MAX_CONFIG_PARAM_NAME_LEN], value[MAX_CONFIG_PARAM_VALUE_LEN];
785 FILE *fp = fopen (CONFIG_FILE_NAME, "r");
786
787 if (fp == NULL)
788 {
789 printf("No config file (%s) found\n", CONFIG_FILE_NAME);
790 return;
791 }
792
793 printf("BAL configuration params as read from %s:\n", CONFIG_FILE_NAME);
794
795 /* Read next line */
796 while ((s = fgets (buff, sizeof buff, fp)) != NULL)
797 {
798 /* Skip blank lines and comments */
799 if (buff[0] == '\n' || buff[0] == '#')
800 continue;
801
802 /* Parse name/value pair from line */
803 s = strtok (buff, "=");
804 if (s==NULL)
805 {
806 continue;
807 }
808 else
809 {
810 strncpy (name, s, MAX_CONFIG_PARAM_NAME_LEN);
811 }
812
813 s = strtok (NULL, "=");
814
815 if (s==NULL)
816 {
817 continue;
818 }
819 else
820 {
821 strncpy (value, s, MAX_CONFIG_PARAM_VALUE_LEN);
822 }
823
824 trim (value);
825
826 printf("%s=%s\n", name, value);
827
828 /* Copy into correct entry in parameters struct */
829 if(strcmp(name, "iwf_mode")==0)
830 {
831 p_params->iwf_mode = find_val_by_enum_name(iwf_mode_enum, value);
832 }
833 else if(strcmp(name, "intf_maptable")==0)
834 {
835 uint32_t intf_map_tbl_idx;
836
837 intf_map_tbl_idx = atoi(value);
838
839 if(BCM_ERR_OK != bal_bcm_intf_maptable_set(intf_map_tbl_idx))
840 {
841 printf("error: value (%u) is not a valid index, ignored", intf_map_tbl_idx);
842 }
843 else
844 {
845 p_params->intf_maptable = atoi(value);
846 }
847 }
848 else if(strcmp(name, "trap_udp_port")==0)
849 {
850 uint32_t udp_port;
851
852 udp_port = atoi(value);
853
854 if(BCM_ERR_OK != bal_bcm_trap_rcv_port_set(udp_port))
855 {
856 printf("error: value (%u) is not a valid port, ignored", udp_port);
857 }
858 else
859 {
860 p_params->trap_udp_port = udp_port;
861 }
862 }
863 else if(strcmp(name, "ds_sched_mode")==0)
864 {
865 uint32_t sched_mode;
866
867 sched_mode = atoi(value);
868
869 if(BCM_ERR_OK != bal_bcm_ds_sched_mode_set(sched_mode))
870 {
871 printf("error: value (%u) is not a valid sched mode, ignored", sched_mode);
872 }
873 else
874 {
875 p_params->ds_sched_mode = sched_mode;
876 }
877 }
878 else if(strcmp(name, "num_nni_ports")==0)
879 {
880
881 p_params->num_nni_ports = atoi(value);
882 bcm_topo_dev_set_max_nni(0, p_params->num_nni_ports);
883
884 }
885 else if(strcmp(name, "pkt_send_svr_listen_port")==0)
886 {
887
888 p_params->pkt_send_svr_listen_port = atoi(value);
889
890 }
891 else if(strcmp(name, "topology.num_of_devs")==0)
892 {
893 p_params->topo_params.num_of_devs = atoi(value);
894 }
895 else if(strcmp(name, "topology.num_of_pons_per_dev")==0)
896 {
897 p_params->topo_params.num_of_pons_per_dev = atoi(value);
898 }
899 else if(strcmp(name, "topology.pon_mode")==0)
900 {
901 if(strcmp(value, "gpon")==0)
902 p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_GPON;
903 else if(strcmp(value, "xgpon")==0)
904 p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_XGPON;
905 else if(strcmp(value, "xgs")==0)
906 p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_XGS;
907 else if(strcmp(value, "epon_tdma")==0)
908 p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_TDMA;
909 else if(strcmp(value, "epon_1g")==0)
910 p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_1G;
911 else if(strcmp(value, "epon_10g")==0)
912 p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_10G;
913 }
914 else if(strcmp(name, "mac_loopback")==0)
915 {
916 if(strcmp(value, "y")==0)
917 {
918 p_params->loopback_modes_bit_mask |= BIT_FIELD_MAC_IN_LOOPBACK;
919 }
920 }
921#ifdef OMCI_SVC
922 else if(strcmp(name, "omci_loopback")==0)
923 {
924 if(strcmp(value, "y")==0)
925 {
926 omci_svc_set_loopback(BCMOS_TRUE);
927 }
928 }
929#endif
930 else if(strncmp(name, "autoneg_nni", 11)==0)
931 {
932 int intf_id = atoi(name+11);
933 if ((unsigned)intf_id >= BAL_API_MAX_INTF_ID)
934 {
935 printf("error: %s: NNI %d is invalid, ignored", name, intf_id);
936 continue;
937 }
938 if(strcmp(value, "y")==0)
939 {
940 p_params->nni_autoneg_bit_mask |= (1 << intf_id);
941 }
942 }
943
944 else
945 {
946 printf("%s/%s: Unknown name/value config file pair!\n",name, value);
947 }
948 }//while
949
950 printf("\n");
951
952 /* Close file */
953 fclose (fp);
954}
955
956static bcmos_errno bal_rpc_soc_gen(void)
957{
958#ifndef TEST_SW_UTIL_LOOPBACK
959#ifdef CONFIG_SWITCH_RPC
960 char cmd[MAX_CMD_LINE_LEN];
961 FILE *fp = fopen (RPC_SOC_TEMPLATE_FILE_NAME, "r");
962 int rc;
963
964 if (fp == NULL)
965 {
966 printf("%s not found\n", RPC_SOC_TEMPLATE_FILE_NAME);
967 return BCM_ERR_NOENT;
968 }
969 fclose (fp);
970
971 snprintf(cmd, MAX_CMD_LINE_LEN, "sed -e \"s/\\\\\\$DIP\\\\$/%s/\" %s > %s",
972 bal_config_params.sw_rpc_ip, RPC_SOC_TEMPLATE_FILE_NAME, RPC_SOC_FILE_NAME);
973 rc = system(cmd);
974 if (rc || WEXITSTATUS(rc))
975 {
976 printf("Failed to generate %s from %s\n", RPC_SOC_FILE_NAME, RPC_SOC_TEMPLATE_FILE_NAME);
977 return BCM_ERR_INTERNAL;
978 }
979#endif
980#endif
981 return BCM_ERR_OK;
982}
983
984
985uint16_t bcmbal_num_nni_ports_get(void)
986{
987 return bal_config_params.num_nni_ports;
988}
989
990bcmos_bool bcmbal_is_mac_in_loopback(void)
991{
992 return IS_MAC_IN_LOOPBACK(bal_config_params.loopback_modes_bit_mask);
993}
994
995bcmos_bool bcmbal_is_nni_autoneg_on(bcmbal_intf_id intf_id)
996{
997 return IS_NNI_INTF_AUTONEG_ON(bal_config_params.nni_autoneg_bit_mask, intf_id);
998}
999
1000/* Get supported command line argument list */
1001int bcmbal_supported_args_get(cl_argument supported_args[], int size)
1002{
1003 int i;
1004 for (i=0; i<BCM_SIZEOFARRAY(supported_cl_args); i++)
1005 {
1006 if (i < size)
1007 supported_args[i] = supported_cl_args[i];
1008 }
1009 return i;
1010}
1011
1012/* Get BAL configuration */
1013const bcmbal_config_params *bcmbal_config_get(void)
1014{
1015 return &bal_config_params;
1016}
1017
1018/*@}*/