blob: fcc1573b8b257db3c66627434f323c85b4a5aa1b [file] [log] [blame]
/******************************************************************************
*
* <: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;
}
/*@}*/