| /****************************************************************************** |
| * |
| * <:copyright-BRCM:2016:DUAL/GPL:standard |
| * |
| * Copyright (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. |
| * |
| * :> |
| * |
| *****************************************************************************/ |
| |
| /** |
| * @file bal_core.c |
| * @brief The code that comprises the main entry point and initialization |
| * code for the BAL Core. |
| * |
| * @addtogroup ctrlr |
| */ |
| |
| /*@{*/ |
| |
| #include <bcmos_system.h> |
| #include <bcmcli.h> |
| #include <bal_switch_util.h> |
| #include <bal_mac_util.h> |
| #include <bal_version.h> |
| #include <cmdline.h> |
| #include <bal_core.h> |
| #include <bal_cli.h> |
| |
| #include "rsc_mgr.h" |
| #include "bal_worker.h" |
| #include "bal_switch_acc_term.h" |
| |
| #ifdef ENABLE_LOG |
| #include <bcm_dev_log.h> |
| #endif |
| |
| #ifdef OMCI_SVC |
| #include <omci_svc.h> |
| #endif |
| |
| #if defined(CONFIG_MAC_RPC) |
| #define CONFIG_MAC_UTIL_IP_PORT |
| #endif |
| |
| #ifdef ENABLE_LOG |
| /* |
| * @brief The Logging device id for the BAL core |
| */ |
| dev_log_id log_id_core; |
| #endif |
| |
| |
| /*--- local function declarations ---*/ |
| static void welcome_to_bal(void); |
| static bcmos_errno bal_core_init(void); |
| static void bal_core_finish(void); |
| static void bal_parse_config(struct bcmbal_config_params *p_params); |
| static bcmos_errno bal_rpc_soc_gen(void); |
| |
| /* |
| * Worker thread and RX thread(s) data structures |
| */ |
| static bcmos_task core_worker_thread; |
| |
| static bcmos_errno _usage(const char *cmd); |
| |
| #define BAL_CHECK_IP_ARGUMENT(_i, _argc, _option) \ |
| do { \ |
| if (_i == _argc - 1) \ |
| { \ |
| printf("Error: IP:port is expected after %s option\n", _option); \ |
| return _usage(argv[0]);\ |
| }\ |
| } while (0) |
| |
| |
| #define CORE_MGMT_IP_PORT_CMDLINE_OPT "-C" |
| #define BAL_API_IP_PORT_CMDLINE_OPT "-A" |
| #define BAL_MAC_IP_PORT_CMDLINE_OPT "-M" |
| #define BAL_SW_IP_CMDLINE_OPT "-S" |
| #define BAL_INIT_SCRIPT_OPT "-f" |
| #define BAL_LOG_FILE_OPT "-F" |
| #define BAL_HELP_OPT "-h" |
| #define BAL_LONG_HELP_OPT "--help" |
| #define BAL_LEVEL_OPT "-L" |
| #define BAL_NO_LOG_OPT "-nl" |
| #define BAL_LOG_SYSLOG_OPT "-syslog" |
| #define BAL_NO_LINEEDIT_OPT "-ne" |
| |
| |
| /* Command line arguments */ |
| static cl_argument supported_cl_args[] = |
| { |
| #ifdef CONFIG_MAC_UTIL_IP_PORT |
| { .short_name = BAL_MAC_IP_PORT_CMDLINE_OPT, |
| .extra_arg = "mac_device_ip:port", |
| .description = "IP address:UDP port where the MAC device listens for RPC messages", |
| .flags = CL_ARGUMENT_FLAG_MANDATORY, |
| .owner = "BAL" |
| }, |
| #endif |
| #ifdef CONFIG_SWITCH_RPC |
| { .short_name = BAL_SW_IP_CMDLINE_OPT, |
| .extra_arg = "switch_ip", |
| .description = "Switch IP address for RPC messages", |
| .flags = CL_ARGUMENT_FLAG_MANDATORY, |
| }, |
| #endif |
| { .short_name = CORE_MGMT_IP_PORT_CMDLINE_OPT, |
| .extra_arg = "core_mgmt_ip:port", |
| .description = "IP address:UDP port where the core listens for messages from the BAL Public API", |
| }, |
| { .short_name = BAL_API_IP_PORT_CMDLINE_OPT, |
| .extra_arg = "al_api_mgmt ip:port", |
| .description = "IP address:UDP port where BAL Public API listens for responses from the core", |
| }, |
| { .short_name = BAL_LEVEL_OPT, |
| .extra_arg = "level", |
| .description = "CLI level: guest | admin | debug", |
| }, |
| { .short_name = BAL_NO_LINEEDIT_OPT, |
| .description = "Disable line editing", |
| }, |
| { .short_name = BAL_INIT_SCRIPT_OPT, |
| .extra_arg = "script_file_name", |
| .description = "Script containing BAL CLI commands", |
| }, |
| #ifdef ENABLE_LOG |
| { .short_name = BAL_LOG_FILE_OPT, |
| .extra_arg = "log_file_name", |
| .description = "Log into file", |
| }, |
| { .long_name = BAL_LOG_SYSLOG_OPT, |
| .description = "Log to syslog", |
| }, |
| { .short_name = BAL_NO_LOG_OPT, |
| .description = "Disable logger", |
| }, |
| #endif |
| #ifndef BUILD_OF_AGENT |
| { .short_name = BAL_HELP_OPT, |
| .long_name = BAL_LONG_HELP_OPT, |
| .description = "This help", |
| }, |
| #endif |
| }; |
| |
| /* |
| * The BAL core config file definitions |
| */ |
| |
| #define TOPOLOGY_FILE_NAME "bal_topology.ini" |
| #define CONFIG_FILE_NAME "bal_config.ini" |
| #define MAX_CONFIG_FILE_LINE_LEN 256 |
| #define MAX_CONFIG_PARAM_NAME_LEN 64 |
| #define MAX_CONFIG_PARAM_VALUE_LEN 64 |
| |
| bcmbal_config_params bal_config_params = |
| { |
| .iwf_mode = BCMBAL_IWF_MODE_PER_FLOW, |
| .intf_maptable = 2, |
| .num_nni_ports = BCM_TOPO_MAX_NNI_PORTS, |
| /* The interface mapping table default value is set in the switch utilities */ |
| .topo_params.pon_mode = BCM_TOPO_PON_MODE_INVALID, |
| /* Default CLI session parameters */ |
| .access = BCMCLI_ACCESS_ADMIN, |
| .edit_mode = BCMCLI_LINE_EDIT_DEFAULT, |
| }; |
| static bcmos_bool bal_initialized; |
| |
| #define RPC_SOC_TEMPLATE_FILE_NAME "rpc.soc.template" |
| #define RPC_SOC_FILE_NAME "rpc.soc" |
| #define MAX_CMD_LINE_LEN 256 |
| |
| /* |
| * An enumeration of the possible iwf modes |
| */ |
| static bcmcli_enum_val iwf_mode_enum[] = { |
| { .name="direct", .val=BCMBAL_IWF_MODE_DIRECT_MAPPING}, |
| { .name="per_flow", .val=BCMBAL_IWF_MODE_PER_FLOW}, |
| BCMCLI_ENUM_LAST |
| }; |
| |
| /** |
| * @brief The Broadcom Ltd logo. |
| */ |
| static const char *g_p_company_logo = |
| "\n\n" |
| " *\n" |
| " * *\n" |
| " * *\n" |
| " * *\n" |
| " * *\n" |
| " * *\n" |
| " * *\n" |
| " * * * * * *\n" |
| " * * * *\n\n" |
| "Copyright (c) 2017 Broadcom Ltd\n\n"; |
| |
| |
| #ifdef ENABLE_LOG |
| /* Create log_id for the core */ |
| static void bal_core_log_init(void) |
| { |
| /* Register the core logging context */ |
| log_id_core = bcm_dev_log_id_register("CORE_CTRLR", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| BUG_ON(log_id_core == DEV_LOG_INVALID_ID); |
| |
| bcm_dev_log_level_set_style(DEV_LOG_LEVEL_FATAL, BCM_DEV_LOG_STYLE_BOLD); |
| bcm_dev_log_level_set_style(DEV_LOG_LEVEL_ERROR, BCM_DEV_LOG_STYLE_BOLD); |
| |
| BCM_LOG(DEBUG, log_id_core, "BAL Core is starting\n"); |
| } |
| |
| /* Initialize logger */ |
| static int bal_dev_log_time_to_str_cb(uint32_t bal_time, char *time_str, int time_str_size) |
| { |
| /* Round timestamp to the nearest ms */ |
| uint32_t time_ms = (bal_time + 500) / 1000; |
| return snprintf(time_str, time_str_size, "%05u.%03u", time_ms / 1000, time_ms % 1000); |
| } |
| #endif |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to initialize the system logging subsystem |
| * |
| * This function is executed at system startup time |
| * |
| *****************************************************************************/ |
| bcmos_errno bcmbal_log_init(void) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| #ifdef ENABLE_LOG |
| const char *log_file_name = bal_config_params.log_file_name; |
| if (bal_config_params.disable_log) |
| return BCM_ERR_OK; |
| do |
| { |
| if (NULL == log_file_name && !bal_config_params.log_syslog) |
| { |
| #define DEV_LOG_SIZE1 1<<20 |
| #define DEV_LOG_QUEUE_SIZE 1000 |
| static uint8_t logger_buf1[DEV_LOG_SIZE1]; |
| void *addresses[DEV_LOG_MAX_FILES] = {logger_buf1}; |
| uint32_t sizes[DEV_LOG_MAX_FILES] = {sizeof(logger_buf1)}; |
| uint32_t flags[DEV_LOG_MAX_FILES] = {BCM_DEV_LOG_FILE_FLAG_WRAP_AROUND}; |
| /* Initialize the system logger for the core threads */ |
| ret = bcm_dev_log_init_default_logger(addresses, |
| sizes, |
| flags, |
| BCM_SIZEOFARRAY(addresses), |
| 0x4000, |
| TASK_PRIORITY_DEV_LOG, |
| DEV_LOG_QUEUE_SIZE); |
| } |
| else |
| { |
| bcm_dev_log_parm dev_log_parm = {}; |
| int nfiles = 0; |
| if (NULL != log_file_name) |
| { |
| dev_log_parm.log_file[nfiles].type = BCM_DEV_LOG_FILE_REGULAR; |
| dev_log_parm.log_file[nfiles].udef_parms = (char *)(long)log_file_name; |
| dev_log_parm.log_file[nfiles].flags = BCM_DEV_LOG_FILE_FLAG_VALID; |
| ++nfiles; |
| }; |
| if (bal_config_params.log_syslog) |
| { |
| dev_log_parm.log_file[nfiles].type = BCM_DEV_LOG_FILE_SYSLOG; |
| dev_log_parm.log_file[nfiles].udef_parms = "BAL"; |
| dev_log_parm.log_file[nfiles].flags = BCM_DEV_LOG_FILE_FLAG_VALID; |
| ++nfiles; |
| }; |
| ret = bcm_dev_log_init_default_logger_ext(&dev_log_parm, |
| nfiles, /* Log into file and/or syslog */ |
| 0x4000, |
| TASK_PRIORITY_DEV_LOG, |
| DEV_LOG_QUEUE_SIZE); |
| } |
| |
| if(BCM_ERR_OK != ret) |
| { |
| printf("Error initializing logger default values (%s)\n", bcmos_strerror(ret)); |
| break; |
| } |
| |
| bcm_dev_log_set_time_to_str_cb(bal_dev_log_time_to_str_cb); |
| } |
| while(0); |
| #endif /* #ifdef ENABLE_LOG */ |
| |
| return ret; |
| } |
| |
| |
| /* Parse command line parameters */ |
| bcmos_errno bcmbal_cmdline_parse(int argc, char *argv[]) |
| { |
| int i; |
| |
| if (cl_validate(argc, argv, supported_cl_args, BCM_SIZEOFARRAY(supported_cl_args)) != BCM_ERR_OK) |
| return _usage(argv[0]); |
| |
| /* |
| * Parse all optional arguments |
| */ |
| for (i = 1; i < argc; i++) |
| { |
| if (!strcmp(argv[i], CORE_MGMT_IP_PORT_CMDLINE_OPT)) |
| { |
| BAL_CHECK_IP_ARGUMENT(i, argc, CORE_MGMT_IP_PORT_CMDLINE_OPT); |
| bal_config_params.core_mgmt_ip_port = argv[++i]; |
| } |
| else if (!strcmp(argv[i], BAL_API_IP_PORT_CMDLINE_OPT)) |
| { |
| BAL_CHECK_IP_ARGUMENT(i, argc, BAL_API_IP_PORT_CMDLINE_OPT); |
| bal_config_params.balapi_mgmt_ip_port = argv[++i]; |
| } |
| #ifdef CONFIG_MAC_UTIL_IP_PORT |
| else if (!strcmp(argv[i], BAL_MAC_IP_PORT_CMDLINE_OPT)) |
| { |
| /* When we build for x86, this is a necessary argument, because the MAC device is |
| * remote from the BAL core. When we build for WRX, this argument isn't required |
| * because the MAC device is local and the mac_rpc_ip_port value is not used. |
| */ |
| BAL_CHECK_IP_ARGUMENT(i, argc, BAL_MAC_IP_PORT_CMDLINE_OPT); |
| bal_config_params.mac_rpc_ip_port = argv[++i]; |
| } |
| #endif |
| #ifdef CONFIG_SWITCH_RPC |
| else if (!strcmp(argv[i], BAL_SW_IP_CMDLINE_OPT)) |
| { |
| BAL_CHECK_IP_ARGUMENT(i, argc, BAL_SW_IP_CMDLINE_OPT); |
| bal_config_params.sw_rpc_ip = argv[++i]; |
| } |
| #endif |
| else if (!strcmp(argv[i], BAL_LEVEL_OPT)) |
| { |
| ++i; |
| if (!strcmp(argv[i], "admin")) |
| bal_config_params.access = BCMCLI_ACCESS_ADMIN; |
| else if (!strcmp(argv[i], "guest")) |
| bal_config_params.access = BCMCLI_ACCESS_GUEST; |
| else if (!strcmp(argv[i], "debug")) |
| bal_config_params.access = BCMCLI_ACCESS_DEBUG; |
| else |
| return _usage(argv[0]); |
| } |
| else if (!strcmp(argv[i], BAL_NO_LINEEDIT_OPT)) |
| { |
| bal_config_params.edit_mode = BCMCLI_LINE_EDIT_DISABLE; |
| } |
| #ifdef ENABLE_LOG |
| else if (!strcmp(argv[i], BAL_NO_LOG_OPT)) |
| { |
| bal_config_params.disable_log = BCMOS_TRUE; |
| } |
| else if (!strcmp(argv[i], BAL_LOG_SYSLOG_OPT)) |
| { |
| bal_config_params.log_syslog = BCMOS_TRUE; |
| } |
| else if (!strcmp(argv[i], BAL_LOG_FILE_OPT)) |
| { |
| if (i == argc - 1) |
| { |
| bcmos_printf("Log file name is expected after %s option\n", BAL_LOG_FILE_OPT); |
| return _usage(argv[0]); |
| } |
| bal_config_params.log_file_name = argv[++i]; |
| } |
| #endif |
| else if (!strcmp(argv[i], BAL_INIT_SCRIPT_OPT)) |
| { |
| if (i == argc - 1) |
| { |
| bcmos_printf("Script file name is expected after %s option\n", BAL_INIT_SCRIPT_OPT); |
| return _usage(argv[0]); |
| } |
| bal_config_params.init_script = argv[++i]; |
| } |
| else if (!strcmp(argv[i], BAL_HELP_OPT) || !strcmp(argv[i], BAL_LONG_HELP_OPT)) |
| { |
| return _usage(argv[0]); |
| } |
| else |
| { |
| /* We have encountered a non-mandatory command line option |
| * that we don't recognize. This is a fatal error. Print |
| * the proper command line invocation. |
| */ |
| printf("Error: unrecognized cmdline option specified (%s)\n", argv[i]); |
| return _usage(argv[0]); |
| } |
| } |
| |
| /* |
| * The user MUST specify the mac and switch IP:port for IPC |
| */ |
| if (BCMOS_FALSE |
| #ifndef BAL_MONOLITHIC |
| || (NULL == bal_config_params.core_mgmt_ip_port) || (NULL == bal_config_params.balapi_mgmt_ip_port) |
| #endif |
| #ifdef CONFIG_MAC_UTIL_IP_PORT |
| || ((BCMOS_TRUE != bcmbal_is_mac_in_loopback()) && (NULL == bal_config_params.mac_rpc_ip_port)) |
| #endif |
| #ifdef CONFIG_SWITCH_RPC |
| || (NULL == bal_config_params.sw_rpc_ip) |
| #endif |
| ) |
| { |
| printf("Error: you must enter ALL mandatory cmdline options\n"); |
| return _usage(argv[0]); |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| /* This is BAL initialization function that is called when BAL is compiled |
| * as a library rather than stand-alone application. |
| * \param[in] argc Number of command line parameters |
| * \param[in] argv Command line parameter array |
| * \returns BCM_ERR_OK (0) if successful or error<0 in case of failure |
| */ |
| bcmos_errno bcmbal_init(void) |
| { |
| bcmos_errno ret; |
| |
| /* Read the bal config file (bal_config.ini) parameters, if the config file is present */ |
| bal_parse_config(&bal_config_params); |
| |
| /* Now initialize the system topology */ |
| ret = bcm_topo_init((bal_config_params.topo_params.num_of_devs && |
| bal_config_params.topo_params.num_of_pons_per_dev && |
| bal_config_params.topo_params.pon_mode != BCM_TOPO_PON_MODE_INVALID) ? |
| &bal_config_params.topo_params : NULL, TOPOLOGY_FILE_NAME); |
| |
| if(BCM_ERR_OK != ret) |
| { |
| bcmos_printf("Error initializing the system topology\n"); |
| return ret; |
| } |
| |
| #ifdef ENABLE_LOG |
| bal_core_log_init(); |
| #endif |
| |
| /* Generate rpc.soc from rpc.soc.template */ |
| if (BCM_ERR_OK != (ret = bal_rpc_soc_gen())) |
| return ret; |
| |
| do |
| { |
| |
| /* Initialize the BAL core itself |
| * NOTE: It is assumed that logging has been successfully |
| * initialized before this call is made |
| */ |
| ret = bal_core_init(); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Error initializing the bal core\n"); |
| break; |
| } |
| |
| /* Initialize the switch utilities */ |
| ret = sw_util_init(); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Error initializing the bal switch utilities\n"); |
| break; |
| } |
| |
| /* Initialize the mac utilities */ |
| ret = mac_util_init(bal_config_params.mac_rpc_ip_port); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Error initializing the bal mac utilities\n"); |
| break; |
| } |
| |
| /* Initialize the bal public api */ |
| ret = bcmbal_api_init(bal_config_params.balapi_mgmt_ip_port, bal_config_params.core_mgmt_ip_port); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Could not initialize the BAL Public API\n"); |
| break; |
| } |
| |
| bal_initialized = BCMOS_TRUE; |
| |
| /* Print out the welcome banner */ |
| welcome_to_bal(); |
| } |
| while(0); |
| |
| return ret; |
| } |
| |
| void bcmbal_finish(void) |
| { |
| bcmbal_cli_finish(); |
| if (bal_initialized) |
| bal_core_finish(); |
| } |
| |
| /* Top-level init sequence */ |
| bcmos_errno bcmbal_init_all(int argc, char *argv[], bcmbal_exit_cb exit_cb) |
| { |
| bcmos_errno err; |
| err = bcmbal_cmdline_parse(argc, argv); |
| err = (err != BCM_ERR_OK) ? err : bcmos_init(); |
| err = (err != BCM_ERR_OK) ? err : bcmbal_log_init(); |
| err = (err != BCM_ERR_OK) ? err : bcmbal_init(); |
| err = (err != BCM_ERR_OK) ? err : bcmbal_cli_init(exit_cb); |
| return err; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The BAL core command line usage function |
| * |
| * A function to display the proper bal_core command line format |
| * |
| * @param cmd A pointer to the command line string that the user entered to |
| * start the BAL core. |
| * |
| * @returns BCM_ERR_PARM - This function is always run as a result of the user |
| * entering an invalid value on the command line. |
| * |
| *****************************************************************************/ |
| static bcmos_errno _usage(const char *cmd) |
| { |
| #ifndef BUILD_OF_AGENT |
| /* For SDN_AGENT all parm usage info is printed in the agent's main */ |
| cl_print_usage(cmd, NULL, supported_cl_args, BCM_SIZEOFARRAY(supported_cl_args), CL_ARGUMENT_USAGE_FLAG_NONE); |
| #endif |
| return BCM_ERR_PARM; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The BAL core initialization function |
| * |
| * A function to initialize the BAL core and all its associated threads. |
| * |
| * @returns BCM_ERR_OK, or the return value from first function called |
| * that fails. |
| * |
| *****************************************************************************/ |
| static bcmos_errno bal_core_init(void) |
| { |
| bcmos_task_parm task_p = {}; |
| bcmos_module_parm module_p = {}; |
| bcmos_errno ret = BCM_ERR_OK; |
| mgmt_queue_addr_ports mgmt_queue_info; |
| |
| do |
| { |
| /* Create message queues */ |
| mgmt_queue_info.core_mgmt_ip_port = bal_config_params.core_mgmt_ip_port; |
| mgmt_queue_info.balapi_mgmt_ip_port = bal_config_params.balapi_mgmt_ip_port; |
| ret = core_msg_queue_init(&mgmt_queue_info); |
| if (BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Couldn't create message queues\n"); |
| break; |
| } |
| |
| /* Create worker thread & modules for mgmt messages */ |
| task_p.name = "core_worker"; |
| task_p.priority = TASK_PRIORITY_WORKER; |
| |
| ret = bcmos_task_create(&core_worker_thread, &task_p); |
| if (BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Couldn't create worker thread\n"); |
| break; |
| } |
| |
| /* |
| * Initialize the worker thread that was just spawned |
| */ |
| core_worker_thread_init(); |
| |
| /* |
| * Now create the module for the worker thread |
| */ |
| module_p.qparm.name = "core_worker_mgmt_module"; |
| module_p.init = _bal_worker_mgmt_module_init; |
| ret = bcmos_module_create(BCMOS_MODULE_ID_WORKER_MGMT, &core_worker_thread, &module_p); |
| if (ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Couldn't create mgmt worker module\n"); |
| break; |
| } |
| |
| #ifdef CONFIG_SWITCH_RPC |
| ret = sw_util_pkt_send_init(bal_config_params.sw_rpc_ip, bal_config_params.pkt_send_svr_listen_port); |
| if (BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_core, "Couldn't initialize the packet send interface ret = %d\n", ret); |
| break; |
| } |
| else |
| { |
| BCM_LOG(DEBUG, log_id_core, |
| "\"Packet send\" interface is initialized" |
| " to use server at %s:%d\n", |
| bal_config_params.sw_rpc_ip, bal_config_params.pkt_send_svr_listen_port ); |
| } |
| #endif |
| } |
| while(0); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The BAL core finish function |
| * |
| * A function to clean up the BAL core and all its associated threads on |
| * exit. |
| * |
| * @returns BCM_ERR_OK |
| * |
| *****************************************************************************/ |
| static void bal_core_finish(void) |
| { |
| rsc_mgr_uninit(); |
| mac_util_finish(); |
| sw_util_finish(); |
| |
| core_worker_thread_finish(); |
| |
| bcmos_module_destroy(BCMOS_MODULE_ID_WORKER_MGMT); |
| |
| bcmos_task_destroy(&core_worker_thread); |
| |
| /* Let logger task have enough time to drain its message queue. */ |
| #ifdef ENABLE_LOG |
| bcmos_usleep(1000000); |
| bcm_dev_log_destroy(); |
| #endif |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to print the welcome banner for BAL |
| * |
| * This function is executed at system startup time |
| * |
| *****************************************************************************/ |
| static void welcome_to_bal(void) |
| { |
| time_t tm = time(NULL); |
| |
| /* @todo Don't print the welcome banner when running as a daemon */ |
| |
| printf("%s", g_p_company_logo); |
| |
| BCM_LOG(INFO, log_id_core, "*** Welcome to BAL %s version %s (Built: %s)\n", |
| #ifndef BUILD_OF_AGENT |
| "", |
| #else |
| "OF-Agent", |
| #endif |
| BAL_VERSION, BAL_BUILD_DATE); |
| BCM_LOG(INFO, log_id_core, "%s\n", BAL_BUILD_INFO); |
| |
| BCM_LOG(INFO, log_id_core, "Time is: %s", asctime(localtime(&tm))); |
| |
| #ifdef TEST_SW_UTIL_LOOPBACK |
| BCM_LOG(INFO, log_id_core, "----BUILT WITH TEST_SW_UTIL_LOOPBACK\n"); |
| #endif |
| |
| if (BCMOS_TRUE == bcmbal_is_mac_in_loopback()) |
| { |
| BCM_LOG(INFO, log_id_core, "----CONFIGURED WITH MAC UTIL LOOPBACK\n"); |
| } |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A trim helper function |
| * |
| * This function is used to get rid of trailing and leading whitespace |
| * including the "\n" from fgets() |
| * |
| * @param s A pointer to the string that is to be trimmed |
| * |
| * @returns -char *, the trimmed sting |
| * |
| */ |
| static char *trim (char * s) |
| { |
| /* Initialize start, end pointers */ |
| int len = strlen(s); |
| char *s1 = s, *s2 = &s[len - 1]; |
| |
| /* Trim and delimit right side */ |
| while ( (isspace (*s2)) && (s2 >= s1) ) |
| { |
| s2--; |
| len--; |
| } |
| |
| *(s2+1) = '\0'; |
| |
| /* Trim left side */ |
| while ( (isspace (*s1)) && (s1 < s2) ) |
| { |
| s1++; |
| len--; |
| } |
| |
| /* Copy finished string. Use memmove, as it is guaranteed to correctly handle overlapping strings. */ |
| memmove (s, s1, len + 1); |
| return s; |
| } |
| |
| /* A helper function for finding an enum array entry value, given it's name*/ |
| static long find_val_by_enum_name(bcmcli_enum_val *p_enum_array, const char * name) |
| { |
| long val = -1; |
| int ii; |
| |
| |
| for(ii=0; p_enum_array[ii].name != NULL; ii++) |
| { |
| if(0 == strcmp(name, p_enum_array[ii].name)) |
| { |
| val = p_enum_array[ii].val; |
| } |
| } |
| |
| return val; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function that reads bal config file |
| * |
| * This function is used to read the bal config file into the |
| * bcmbal_config_params structure. |
| * |
| * The config file is defined to be named "bal_config.ini" and is |
| * of the format: |
| * param_name=param_value |
| * |
| * @param p_params A pointer to the core configuration parameters |
| * |
| * @returns void |
| * |
| */ |
| static void bal_parse_config(bcmbal_config_params *p_params) |
| { |
| char *s, buff[MAX_CONFIG_FILE_LINE_LEN]; |
| char name[MAX_CONFIG_PARAM_NAME_LEN], value[MAX_CONFIG_PARAM_VALUE_LEN]; |
| FILE *fp = fopen (CONFIG_FILE_NAME, "r"); |
| |
| if (fp == NULL) |
| { |
| printf("No config file (%s) found\n", CONFIG_FILE_NAME); |
| return; |
| } |
| |
| printf("BAL configuration params as read from %s:\n", CONFIG_FILE_NAME); |
| |
| /* Read next line */ |
| while ((s = fgets (buff, sizeof buff, fp)) != NULL) |
| { |
| /* Skip blank lines and comments */ |
| if (buff[0] == '\n' || buff[0] == '#') |
| continue; |
| |
| /* Parse name/value pair from line */ |
| s = strtok (buff, "="); |
| if (s==NULL) |
| { |
| continue; |
| } |
| else |
| { |
| strncpy (name, s, MAX_CONFIG_PARAM_NAME_LEN); |
| } |
| |
| s = strtok (NULL, "="); |
| |
| if (s==NULL) |
| { |
| continue; |
| } |
| else |
| { |
| strncpy (value, s, MAX_CONFIG_PARAM_VALUE_LEN); |
| } |
| |
| trim (value); |
| |
| printf("%s=%s\n", name, value); |
| |
| /* Copy into correct entry in parameters struct */ |
| if(strcmp(name, "iwf_mode")==0) |
| { |
| p_params->iwf_mode = find_val_by_enum_name(iwf_mode_enum, value); |
| } |
| else if(strcmp(name, "intf_maptable")==0) |
| { |
| uint32_t intf_map_tbl_idx; |
| |
| intf_map_tbl_idx = atoi(value); |
| |
| if(BCM_ERR_OK != bal_bcm_intf_maptable_set(intf_map_tbl_idx)) |
| { |
| printf("error: value (%u) is not a valid index, ignored", intf_map_tbl_idx); |
| } |
| else |
| { |
| p_params->intf_maptable = atoi(value); |
| } |
| } |
| else if(strcmp(name, "trap_udp_port")==0) |
| { |
| uint32_t udp_port; |
| |
| udp_port = atoi(value); |
| |
| if(BCM_ERR_OK != bal_bcm_trap_rcv_port_set(udp_port)) |
| { |
| printf("error: value (%u) is not a valid port, ignored", udp_port); |
| } |
| else |
| { |
| p_params->trap_udp_port = udp_port; |
| } |
| } |
| else if(strcmp(name, "ds_sched_mode")==0) |
| { |
| uint32_t sched_mode; |
| |
| sched_mode = atoi(value); |
| |
| if(BCM_ERR_OK != bal_bcm_ds_sched_mode_set(sched_mode)) |
| { |
| printf("error: value (%u) is not a valid sched mode, ignored", sched_mode); |
| } |
| else |
| { |
| p_params->ds_sched_mode = sched_mode; |
| } |
| } |
| else if(strcmp(name, "num_nni_ports")==0) |
| { |
| |
| p_params->num_nni_ports = atoi(value); |
| bcm_topo_dev_set_max_nni(0, p_params->num_nni_ports); |
| |
| } |
| else if(strcmp(name, "pkt_send_svr_listen_port")==0) |
| { |
| |
| p_params->pkt_send_svr_listen_port = atoi(value); |
| |
| } |
| else if(strcmp(name, "topology.num_of_devs")==0) |
| { |
| p_params->topo_params.num_of_devs = atoi(value); |
| } |
| else if(strcmp(name, "topology.num_of_pons_per_dev")==0) |
| { |
| p_params->topo_params.num_of_pons_per_dev = atoi(value); |
| } |
| else if(strcmp(name, "topology.pon_mode")==0) |
| { |
| if(strcmp(value, "gpon")==0) |
| p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_GPON; |
| else if(strcmp(value, "xgpon")==0) |
| p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_XGPON; |
| else if(strcmp(value, "xgs")==0) |
| p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_XGS; |
| else if(strcmp(value, "epon_tdma")==0) |
| p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_TDMA; |
| else if(strcmp(value, "epon_1g")==0) |
| p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_1G; |
| else if(strcmp(value, "epon_10g")==0) |
| p_params->topo_params.pon_mode = BCM_TOPO_PON_MODE_EPON_10G; |
| } |
| else if(strcmp(name, "mac_loopback")==0) |
| { |
| if(strcmp(value, "y")==0) |
| { |
| p_params->loopback_modes_bit_mask |= BIT_FIELD_MAC_IN_LOOPBACK; |
| } |
| } |
| #ifdef OMCI_SVC |
| else if(strcmp(name, "omci_loopback")==0) |
| { |
| if(strcmp(value, "y")==0) |
| { |
| omci_svc_set_loopback(BCMOS_TRUE); |
| } |
| } |
| #endif |
| else if(strncmp(name, "autoneg_nni", 11)==0) |
| { |
| int intf_id = atoi(name+11); |
| if ((unsigned)intf_id >= BAL_API_MAX_INTF_ID) |
| { |
| printf("error: %s: NNI %d is invalid, ignored", name, intf_id); |
| continue; |
| } |
| if(strcmp(value, "y")==0) |
| { |
| p_params->nni_autoneg_bit_mask |= (1 << intf_id); |
| } |
| } |
| |
| else |
| { |
| printf("%s/%s: Unknown name/value config file pair!\n",name, value); |
| } |
| }//while |
| |
| printf("\n"); |
| |
| /* Close file */ |
| fclose (fp); |
| } |
| |
| static bcmos_errno bal_rpc_soc_gen(void) |
| { |
| #ifndef TEST_SW_UTIL_LOOPBACK |
| #ifdef CONFIG_SWITCH_RPC |
| char cmd[MAX_CMD_LINE_LEN]; |
| FILE *fp = fopen (RPC_SOC_TEMPLATE_FILE_NAME, "r"); |
| int rc; |
| |
| if (fp == NULL) |
| { |
| printf("%s not found\n", RPC_SOC_TEMPLATE_FILE_NAME); |
| return BCM_ERR_NOENT; |
| } |
| fclose (fp); |
| |
| snprintf(cmd, MAX_CMD_LINE_LEN, "sed -e \"s/\\\\\\$DIP\\\\$/%s/\" %s > %s", |
| bal_config_params.sw_rpc_ip, RPC_SOC_TEMPLATE_FILE_NAME, RPC_SOC_FILE_NAME); |
| rc = system(cmd); |
| if (rc || WEXITSTATUS(rc)) |
| { |
| printf("Failed to generate %s from %s\n", RPC_SOC_FILE_NAME, RPC_SOC_TEMPLATE_FILE_NAME); |
| return BCM_ERR_INTERNAL; |
| } |
| #endif |
| #endif |
| return BCM_ERR_OK; |
| } |
| |
| |
| uint16_t bcmbal_num_nni_ports_get(void) |
| { |
| return bal_config_params.num_nni_ports; |
| } |
| |
| bcmos_bool bcmbal_is_mac_in_loopback(void) |
| { |
| return IS_MAC_IN_LOOPBACK(bal_config_params.loopback_modes_bit_mask); |
| } |
| |
| bcmos_bool bcmbal_is_nni_autoneg_on(bcmbal_intf_id intf_id) |
| { |
| return IS_NNI_INTF_AUTONEG_ON(bal_config_params.nni_autoneg_bit_mask, intf_id); |
| } |
| |
| /* Get supported command line argument list */ |
| int bcmbal_supported_args_get(cl_argument supported_args[], int size) |
| { |
| int i; |
| for (i=0; i<BCM_SIZEOFARRAY(supported_cl_args); i++) |
| { |
| if (i < size) |
| supported_args[i] = supported_cl_args[i]; |
| } |
| return i; |
| } |
| |
| /* Get BAL configuration */ |
| const bcmbal_config_params *bcmbal_config_get(void) |
| { |
| return &bal_config_params; |
| } |
| |
| /*@}*/ |