| /****************************************************************************** |
| * |
| * <: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 acc_term_fsm.c |
| * @brief Code to support the BAL access terminal FSM |
| * |
| * @addtogroup access_terminal |
| */ |
| |
| /*@{*/ |
| |
| #define BAL_DBG_PRINT |
| |
| /*--- project includes ---*/ |
| #include <bcmos_system.h> |
| #include <acc_term_fsm.h> |
| #include <bal_msg.h> |
| #include <bal_api.h> |
| #include "bal_worker.h" |
| #include "bal_mac_util.h" |
| #include "bal_switch_util.h" |
| #include <bal_osmsg.h> |
| #include <fsm_common.h> |
| #include <rsc_mgr.h> |
| #include <bal_core.h> |
| |
| #ifdef ENABLE_LOG |
| #include <bcm_dev_log.h> |
| |
| /* |
| * @brief The logging device ids for the access-terminal and interface |
| */ |
| static dev_log_id log_id_access_terminal; |
| static dev_log_id log_id_interface; |
| #endif |
| |
| |
| /*--- local function declarations ---*/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_up_ok(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_acc_term_admin_dn_start(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_acc_term_admin_dn_ok(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_ignore_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_acc_term_admin_up_pending(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_acc_term_admin_dn_pending(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_adding_process_util_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_removing_process_util_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_process_util_auto_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_process_adding_timeout(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_process_removing_timeout(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno acc_term_fsm_acc_term_admin_up_start(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static bcmos_errno interface_admin_up_start(acc_term_interface *p_interface, |
| void *msg); |
| |
| static bcmos_errno interface_admin_dn_start(acc_term_interface *p_interface, |
| void *msg); |
| |
| static bcmos_timer_rc acc_term_fsm_timer_expiry(bcmos_timer *timer, long pUser); |
| |
| static bcmos_errno access_terminal_fsm_exec(acc_term_inst *p_acc_term_inst, acc_term_fsm_event *p_event); |
| |
| |
| /** |
| * access-terminal FSM helper functions |
| */ |
| static bcmos_errno acc_term_fsm_state_err(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event); |
| |
| static void initialize_access_terminal_instance_config(acc_term_inst *p_acc_term_inst); |
| |
| static bcmos_errno sub_term_id_list_fill(uint32_t interface_index, |
| bcmbal_sub_id_list_u16 *sub_term_id_list); |
| |
| |
| static acc_term_inst *access_terminal_get(void); |
| static char *interface_type_str_get(bcmbal_intf_type intf_type); |
| |
| static bcmos_errno interface_tm_sched_set(bcmbal_interface_cfg *p_interface_info); |
| static acc_term_interface * bcmbal_interface_get(bcmbal_interface_key key); |
| |
| #define ACC_TERM_FSM_STATE_ADDING_TIMEOUT (45) /* Seconds */ |
| |
| /* |
| * @brief The definition of an access terminal FSM state processing function |
| */ |
| typedef bcmos_errno (* acc_term_fsm_state_processor)(acc_term_inst *, void *, acc_term_fsm_event *); |
| |
| extern bcmbal_config_params bal_config_params; |
| |
| |
| /** |
| * @brief API to get oper status from admin state of an interface |
| */ |
| bcmbal_status bcmbal_get_intf_oper_status_from_admin_state (bcmbal_state intf_admin_state) |
| { |
| switch (intf_admin_state) |
| { |
| case BCMBAL_STATE_UP: |
| return BCMBAL_STATUS_UP; |
| break; |
| |
| case BCMBAL_STATE_DOWN: |
| return BCMBAL_STATUS_DOWN; |
| break; |
| |
| case BCMBAL_STATE_TESTING: |
| return BCMBAL_STATUS_TESTING; |
| break; |
| |
| default: |
| return BCMBAL_STATUS_UP; /* default keep oper status as UP */ |
| break; |
| } |
| |
| return BCMBAL_STATUS_UP; /* default keep oper status as UP */ |
| } |
| |
| |
| /** |
| * @brief API to convert port type and id from CLI/Mgmt interface to the internal |
| * index of interface array database. |
| */ |
| uint32_t bcmbal_port_type_and_id_to_interface_index (bcmbal_intf_type intf_type, bcmbal_intf_id intf_id) |
| { |
| switch (intf_type) |
| { |
| case BCMBAL_INTF_TYPE_PON: |
| if (intf_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES) |
| { |
| return intf_id; /* zero offset for the PON ports */ |
| } |
| break; |
| |
| case BCMBAL_INTF_TYPE_NNI: |
| if (intf_id < bal_config_params.num_nni_ports) |
| { |
| return (NUM_SUPPORTED_SUBSCRIBER_INTERFACES + intf_id); /* offset-ed for the NNI ports */ |
| } |
| break; |
| |
| default: |
| break; |
| } |
| |
| return INVALID_INTERFACE_INDEX; |
| |
| } |
| |
| |
| /* |
| * @brief The Access terminal FSM state processing array |
| */ |
| static acc_term_fsm_state_processor access_term_states[ACC_TERM_FSM_STATE__NUM_OF][ACC_TERM_FSM_EVENT_TYPE__NUM_OF] = |
| { |
| |
| [ACC_TERM_FSM_STATE_NULL] = |
| { |
| /* |
| * Next state: ADDING |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP] = acc_term_fsm_acc_term_admin_up_start, |
| |
| /* |
| * Next state: NULL |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN] = acc_term_fsm_acc_term_admin_dn_ok, |
| |
| /* |
| * Next state: NULL |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_ignore_msg, |
| |
| /* |
| * Next state: NULL |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg, |
| }, |
| |
| [ACC_TERM_FSM_STATE_ADDING] = |
| { |
| /* |
| * Next state: ADDING |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP] = acc_term_fsm_acc_term_admin_up_pending, |
| |
| /* |
| * Next state: ADDING | ADDED |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_adding_process_util_msg, |
| |
| /* |
| * Next state: ADDING |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg, |
| |
| /* |
| * Next state: NULL |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_TIMEOUT] = acc_term_fsm_process_adding_timeout, |
| |
| }, |
| |
| [ACC_TERM_FSM_STATE_ADDED] = |
| { |
| /* |
| * Next state: ADDED |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP] = acc_term_fsm_acc_term_admin_up_ok, |
| |
| /* |
| * Next state: REMOVING |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN] = acc_term_fsm_acc_term_admin_dn_start, |
| |
| /* |
| * Next state: ADDING | ADDED |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_ignore_msg, |
| |
| /* |
| * Next state: ADDED |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg, |
| |
| }, |
| |
| [ACC_TERM_FSM_STATE_REMOVING] = |
| { |
| /* |
| * Next state: REMOVING |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN] = acc_term_fsm_acc_term_admin_dn_pending, |
| |
| /* |
| * Next state: REMOVING | NULL |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG] = acc_term_fsm_removing_process_util_msg, |
| |
| /* |
| * Next state: REMOVING |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = acc_term_fsm_process_util_auto_msg, |
| |
| /* |
| * Next state: NULL |
| */ |
| [ACC_TERM_FSM_EVENT_TYPE_TIMEOUT] = acc_term_fsm_process_removing_timeout, |
| }, |
| |
| }; |
| |
| static char *state_name_str[] = |
| { |
| "ACC_TERM_NULL", |
| "ACC_TERM_ADDING", |
| "ACC_TERM_ADDED", |
| "ACC_TERM_REMOVING", |
| }; |
| |
| /* Ensure that the name array size matches the associated enum */ |
| BAL_STATIC_ASSERT (ACC_TERM_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), acc_term_fsm_state); |
| |
| static char *acc_term_state_name_get(acc_term_fsm_state state) |
| { |
| if(state < ACC_TERM_FSM_STATE__LAST) |
| { |
| return state_name_str[state]; |
| } |
| else |
| { |
| return "ACC_TERM_UNKNOWN"; |
| } |
| } |
| |
| static char *event_name_str[] = |
| { |
| "ACC_TERM_FSM_ACC_TERM_ADMIN_UP_EVENT", |
| "ACC_TERM_FSM_ACC_TERM_ADMIN_DN_EVENT", |
| "ACC_TERM_FSM_INT_ADMIN_UP_EVENT", |
| "ACC_TERM_FSM_INT_ADMIN_DN_EVENT", |
| "ACC_TERM_FSM_UTIL_MSG_EVENT", |
| "ACC_TERM_FSM_UTIL_AUTO_MSG_EVENT", |
| "ACC_TERM_FSM_TIMEOUT_EVENT" |
| }; |
| |
| /* Ensure that the name array size matches the associated enum */ |
| BAL_STATIC_ASSERT (ACC_TERM_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), acc_term_fsm_event_type); |
| |
| static char *acc_term_event_name_get(acc_term_fsm_event_type event) |
| { |
| if(event < ACC_TERM_FSM_EVENT_TYPE__LAST) |
| { |
| return event_name_str[event]; |
| } |
| else |
| { |
| return "ACC_TERM_EVT_UNKNOWN"; |
| } |
| } |
| |
| static acc_term_inst single_access_terminal_instance; |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function called to initialize the access-terminal FSM |
| * infrastructure. |
| * |
| * NOTE: This is called once on startup and NOT for each FSM instance. |
| * |
| * @returns void |
| *****************************************************************************/ |
| void access_terminal_fsm_init(void) |
| { |
| |
| #ifdef ENABLE_LOG |
| /* Register the log ids for this FSM */ |
| log_id_access_terminal = bcm_dev_log_id_register("ACC_TERM", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| BUG_ON(log_id_access_terminal == DEV_LOG_INVALID_ID); |
| |
| log_id_interface = bcm_dev_log_id_register("INTF", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| BUG_ON(log_id_interface == DEV_LOG_INVALID_ID); |
| #endif |
| |
| /* |
| * Initialize the access terminal instance structures |
| */ |
| initialize_access_terminal_instance_config(&single_access_terminal_instance); |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing executive function |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno access_terminal_fsm_exec(acc_term_inst *p_acc_term_inst, |
| acc_term_fsm_event *p_event) |
| { |
| |
| bcmos_errno ret = BCM_ERR_OK; |
| acc_term_fsm_state pre_state; |
| acc_term_fsm_state_processor acc_term_state_processor; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_acc_term_inst); |
| BUG_ON(NULL == p_event); |
| |
| /* Record the present state before transitioning |
| */ |
| pre_state = p_acc_term_inst->fsm_state; |
| |
| /* |
| * Get the state processing function |
| */ |
| acc_term_state_processor = access_term_states[p_acc_term_inst->fsm_state][p_event->event_type]; |
| |
| /* |
| * If there's a state processing function for this event and state, execute it. |
| * Otherwise, process a generic error. |
| */ |
| if (acc_term_state_processor) |
| { |
| ret = acc_term_state_processor(p_acc_term_inst, p_event->msg, p_event); |
| } else |
| { |
| acc_term_fsm_state_err(p_acc_term_inst, p_event->msg, p_event); |
| } |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, "*** FSM exec: Event %s, State: %s --> %s\n", |
| acc_term_event_name_get(p_event->event_type), |
| acc_term_state_name_get(pre_state), |
| acc_term_state_name_get(p_acc_term_inst->fsm_state)); |
| |
| return ret; |
| } |
| |
| bcmos_errno process_access_terminal_util_msg(void *msg_payload) |
| { |
| acc_term_inst *p_access_terminal_inst; |
| |
| BCM_LOG(INFO, log_id_access_terminal, "ACCESS_TERMINAL indication received from util\n"); |
| |
| /* Find the specified access terminal instance */ |
| p_access_terminal_inst = access_terminal_get(); |
| |
| if (NULL != p_access_terminal_inst) |
| { |
| acc_term_fsm_event event; |
| |
| event.event_type = ACC_TERM_FSM_EVENT_TYPE_UTIL_MSG; |
| event.msg = msg_payload; |
| |
| access_terminal_fsm_exec(p_access_terminal_inst, &event); |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_interface, "Could not find the ACTIVE access-terminal\n"); |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing for an access-terminal |
| * admin-up command received from the BAL Public API when the specified |
| * access-terminal instance is in the admin-down state (i.e. when |
| * the access-terminal instance FSM is in the NULL state). |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_up_start(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| acc_term_fsm_state old_state = p_acc_term_inst->fsm_state; |
| |
| BCM_LOG(INFO, log_id_access_terminal, |
| "Received an admin UP request from BAL API - bringing access terminal up\n"); |
| |
| do |
| { |
| /* change access terminal state to ADDING */ |
| p_acc_term_inst->fsm_state = ACC_TERM_FSM_STATE_ADDING; |
| |
| /* start the timeout timer for the ADDING state */ |
| fsm_timer_start(&p_acc_term_inst->timer_info, |
| p_acc_term_inst, |
| acc_term_fsm_timer_expiry, |
| TIMER_DURATION_IN_SEC(ACC_TERM_FSM_STATE_ADDING_TIMEOUT), |
| log_id_access_terminal); |
| |
| /* Validate that the OLT SW version that the Bal was compiled against matches |
| * the SW version of the actual OLT that the Bal works with. We assume that |
| * Device Id 0 has the same version as all other OLT devices */ |
| if (!bcmbal_is_mac_in_loopback() && |
| (BCM_ERR_OK != (ret = mac_util_access_terminal_sw_version_validate((bcmolt_devid) 0)))) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, "mac_util_access_terminal_sw_version_validate(() failed. rc=%s\n", bcmos_strerror(ret)); |
| break; |
| } |
| |
| /* Core calls Mac Utils to set the access-terminal parameters using the applicable SDK calls */ |
| if(BCM_ERR_OK != (ret = mac_util_access_terminal_set(p_acc_term_inst, BAL_UTIL_OPER_ACC_TERM_CONNECT))) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, "mac_util_access_terminal_set(() failed. rc=%s\n", bcmos_strerror(ret)); |
| break; |
| } |
| |
| }while(0); |
| |
| if(BCM_ERR_OK == ret) |
| { |
| /* |
| * The access-terminal object command has succeeded. The current object info |
| * becomes the commanded object info, except for the oper_status. This should |
| * be done atomically |
| */ |
| memcpy(&p_acc_term_inst->current_acc_term_obj_info, |
| &p_acc_term_inst->api_req_acc_term_obj_info, |
| sizeof(p_acc_term_inst->api_req_acc_term_obj_info)); |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_TRUE); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info, |
| access_terminal, |
| oper_status, |
| BCMBAL_STATUS_DOWN); |
| } |
| else |
| { |
| fsm_timer_stop(&p_acc_term_inst->timer_info); |
| p_acc_term_inst->fsm_state = old_state; |
| mgmt_msg_send_balapi_ind(ret, msg, log_id_access_terminal); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing for an access-terminal |
| * admin-up command from the BAL Public API when the specified |
| * access-terminal is already admin-up (i.e. when the specified |
| * access-terminal instance FSM is in the ADDED state). |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_up_ok(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "Received an admin UP request from BAL API - returning OK to the API" |
| " - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing for an access-terminal |
| * admin-down command received from the BAL Public API when the specified |
| * access-terminal is admin-up (i.e when the specified access-terminal |
| * instance FSM is in the ADDED state). |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_dn_start(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "Received an admin DOWN request from BAL API - removing the access terminal\n"); |
| |
| /* |
| * @todo - complete the DOWN implementation - until then, return an error |
| */ |
| ret = BCM_ERR_NOT_SUPPORTED; |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing for access-terminal |
| * admin-down command from the BAL Public API when the specified |
| * access-terminal is already admin-down. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_dn_ok(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "Received an admin DOWN request from BAL API - returning OK to the API" |
| " - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing function to ignore a |
| * received message. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_ignore_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, "Ignoring message from BAL API \n"); |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing function to process an |
| * access-terminal admin-up command from the BAL Public API when the |
| * specified access-terminal is in the REMOVING state. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_up_pending(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| " Received an admin UP request from BAL API - returning UP_PENDING to the API" |
| " - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing function to process an |
| * access-terminal admin-down command from the BAL Public API when the |
| * specified access-terminal FSM is in the REMOVING state. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_acc_term_admin_dn_pending(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_IN_PROGRESS; |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| " Received an admin DOWN request from BAL API" |
| " - returning IN_PROGRESS to the API - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing function to process a |
| * message from one of the BAL apps when the specified access-terminal |
| * instance FSM is in the ADDING state. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_adding_process_util_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| flow_fsm_state next_state = ACC_TERM_FSM_STATE_NULL; |
| bcmos_errno ret; |
| bal_util_msg_ind *ind_msg; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_acc_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| ind_msg = (bal_util_msg_ind *)msg; |
| |
| ret = ind_msg->status; |
| |
| /* |
| * NOTE: AUTO_IND messages are not processed in this function, |
| * so there is no need to consider them in this logic. |
| */ |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "Received an IND message from BAL UTIL (%s) during ADDING state with status %s\n", |
| subsystem_str[bcmbal_sender_get(msg)], |
| bcmos_strerror(ret) |
| ); |
| } |
| |
| /* |
| * Stop the indication timer |
| */ |
| fsm_timer_stop(&p_acc_term_inst->timer_info); |
| |
| if(BCM_ERR_OK == ret) |
| { |
| /* Core calls Switch Utils to set the access-terminal parameters using the applicable SDK calls */ |
| ret = sw_util_access_terminal_set(p_acc_term_inst, BAL_UTIL_OPER_ACC_TERM_CONNECT); |
| if (ret) |
| { |
| BCM_LOG(INFO, log_id_access_terminal, |
| "sw_util_access_terminal_set(() failed. rc=%s\n", bcmos_strerror(ret)); |
| } |
| |
| if(BCM_ERR_OK == ret) |
| { |
| uint32_t logical_pon; |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info, |
| access_terminal, |
| oper_status, |
| BCMBAL_STATUS_UP); |
| |
| /* |
| * Initialize the resource manager only if at least of the PONs on the device is a GPON/XGPON/XGS/NGPON2 PON |
| */ |
| BCM_TOPO_DEV_FOR_EACH_PON(0, logical_pon) |
| { |
| bcm_topo_pon_family pon_family = bcm_topo_pon_get_pon_family(logical_pon); |
| |
| if (pon_family == BCM_TOPO_PON_FAMILY_GPON) |
| { |
| rsc_mgr_mac_init(); |
| break; |
| } |
| } |
| |
| /* |
| * Go to the ADDED state upon success |
| */ |
| next_state = ACC_TERM_FSM_STATE_ADDED; |
| |
| |
| } |
| else |
| { |
| /* Error */ |
| BCM_LOG(ERROR, log_id_access_terminal, |
| " Failed in state %s;%s\n", |
| acc_term_state_name_get(p_acc_term_inst->fsm_state), |
| bcmos_strerror(ret)); |
| |
| /* |
| * Automatically return to the NULL state if an error occurs |
| */ |
| } |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_FALSE); |
| |
| /* |
| * Send the indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| (void *)&p_acc_term_inst->current_acc_term_obj_info.hdr, |
| log_id_access_terminal); |
| |
| |
| |
| } |
| |
| p_acc_term_inst->fsm_state = next_state; |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing function to process a |
| * message from one of the BAL apps received when the specified |
| * access-terminal instance FSM is in the REMOVING state. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_removing_process_util_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret; |
| bal_util_msg_ind *ind_msg; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_acc_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| ind_msg = (bal_util_msg_ind *)msg; |
| |
| ret = ind_msg->status; |
| |
| /* |
| * NOTE: AUTO_IND messages are not processed in this function, |
| * so there is no need to consider them in this logic. |
| */ |
| |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| " Received an IND message from BAL UTIL (%s) during REMOVING state\n", |
| subsystem_str[bcmbal_sender_get(msg)]); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing function to process an |
| * AUTO IND message from one of the BAL apps. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_process_util_auto_msg(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_acc_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| BCM_LOG(INFO, log_id_access_terminal, |
| " Received an AUTO IND message from BAL UTIL ()\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief Interface admin-up command received from the BAL Public API when |
| * the specified interface instance is in the admin-up state. |
| * |
| * @note This handler gets called for both PON and NNI type interfaces |
| * |
| * @param p_interface_inst Pointer to an interface instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno interface_admin_up_start(acc_term_interface *p_interface_inst, |
| void *msg) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| bcmbal_interface_key *key = &(p_interface_inst->api_req_int_obj_info.key); |
| |
| BCM_LOG(INFO, log_id_interface, |
| " Received an INTERFACE admin UP request from BAL API" |
| " - bringing interface (%s%d) UP \n", |
| interface_type_str_get(key->intf_type), |
| key->intf_id); |
| |
| do |
| { |
| bcmbal_state old_admin_state = p_interface_inst->current_int_obj_info.data.admin_state; |
| |
| /* |
| * Create a pointer to the interface instance specified by the user |
| */ |
| |
| /* |
| * If the user has set the min_data_agg_port_id attribute for the interface, then program the resource manager |
| * with this value. It will also be sent to the MAC device for any required programming there. |
| */ |
| if ((BCMBAL_INTF_TYPE_PON == key->intf_type) && |
| (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&p_interface_inst->api_req_int_obj_info, |
| interface, |
| min_data_agg_port_id)) && |
| (BCM_ERR_OK != rsc_mgr_access_int_base_alloc_id_set(key->intf_id, |
| p_interface_inst->api_req_int_obj_info.data.min_data_agg_port_id))) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, "Error while setting base agg_port_id (%d) in the resource manager\n", |
| p_interface_inst->api_req_int_obj_info.data.min_data_agg_port_id); |
| |
| ret = BCM_ERR_INTERNAL; |
| break; |
| } |
| |
| /* Change the interface admin state of the "current" interface object to up (this is for reporting) */ |
| BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info, |
| interface, |
| admin_state, |
| BCMBAL_STATE_UP); |
| |
| /* Core calls Mac Utils to set the interface parameters using the applicable SDK calls */ |
| ret = mac_util_interface_set(p_interface_inst, BAL_UTIL_OPER_IF_UP); |
| |
| if (BCM_ERR_OK != ret) |
| { |
| BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info, |
| interface, |
| admin_state, |
| old_admin_state); |
| |
| BCM_LOG(ERROR, log_id_interface, |
| "Error detected by mac_util_interface_set (%s)\n", |
| bcmos_strerror(ret)); |
| |
| break; |
| } |
| } while (0); |
| |
| if (BCM_ERR_OK != ret) |
| { |
| /* report this error to the API */ |
| mgmt_msg_send_balapi_ind(ret, |
| msg, |
| log_id_interface); |
| } |
| else |
| { |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_interface_inst->current_int_obj_info), BCMOS_TRUE); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief Interface admin-up command received from the BAL Public API when |
| * the specified interface instance is in the admin-down state. |
| * |
| * @note This handler gets called for both PON and NNI type interfaces |
| * |
| * @param p_interface_inst Pointer to an interface instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno interface_admin_dn_start(acc_term_interface *p_interface_inst, |
| void *msg) |
| { |
| |
| bcmos_errno ret = BCM_ERR_OK; |
| bcmbal_interface_key *key = &(p_interface_inst->api_req_int_obj_info.key); |
| |
| BCM_LOG(INFO, log_id_interface, |
| " Received an INTERFACE admin DOWN request from BAL API" |
| " - bringing interface (%s%d) DOWN \n", |
| interface_type_str_get(key->intf_type), |
| key->intf_id); |
| |
| do |
| { |
| bcmbal_state old_admin_state = p_interface_inst->current_int_obj_info.data.admin_state; |
| |
| /* |
| * Create a pointer to the interface instance specified by the user |
| */ |
| |
| /* Core calls Mac Utils to set the interface parameters using the applicable SDK calls */ |
| ret = mac_util_interface_set(p_interface_inst, BAL_UTIL_OPER_IF_DOWN); |
| |
| if (BCM_ERR_OK != ret) |
| { |
| |
| BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info, |
| interface, |
| admin_state, |
| old_admin_state); |
| |
| BCM_LOG(ERROR, log_id_interface, |
| "Error detected by mac_util_interface_set (%s)\n", |
| bcmos_strerror(ret)); |
| |
| break; |
| } |
| |
| } while (0); |
| |
| /* Change the interface admin state of the current interface info to down */ |
| BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info, |
| interface, |
| admin_state, |
| BCMBAL_STATE_DOWN); |
| |
| /* Check for any error and send an indication immediately in that case */ |
| if (BCM_ERR_OK != ret) |
| { |
| /* report this error to the API */ |
| mgmt_msg_send_balapi_ind(ret, |
| msg, |
| log_id_interface); |
| |
| } |
| else |
| { |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_interface_inst->current_int_obj_info), BCMOS_TRUE); |
| } |
| |
| return ret; |
| |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The function to process a timer expiry for either the ADDING |
| * states. This function executes an |
| * ACC_TERM_FSM_TIMEOUT_EVENT in the FSM state machine. |
| * |
| * @param timer - A pointer to the timer instance |
| * @param pUser - An opaque pointer to an access terminal instance |
| * |
| * @returns bcmos_timer_rc == BCMOS_TIMER_OK |
| */ |
| static bcmos_timer_rc acc_term_fsm_timer_expiry(bcmos_timer *timer, long pUser) |
| { |
| acc_term_fsm_event acc_term_event; |
| |
| /* |
| * Stop the indication timer |
| */ |
| fsm_timer_stop(timer); |
| |
| BCM_LOG(INFO, log_id_access_terminal, |
| "timer expiry\n"); |
| |
| /* |
| * A message pointer is always passed inside the event structure. In this case, it is unused |
| */ |
| acc_term_event.msg = NULL; |
| acc_term_event.event_type = ACC_TERM_FSM_EVENT_TYPE_TIMEOUT; |
| |
| /* Declare this no longer in-progress */ |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(((acc_term_inst *)pUser)->current_acc_term_obj_info), BCMOS_FALSE); |
| |
| /* |
| * Run the access terminal FSM to process this event |
| */ |
| access_terminal_fsm_exec((acc_term_inst *)pUser, &acc_term_event); |
| |
| return BCMOS_TIMER_OK; |
| |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing a timeout that occurs |
| * when the FSM is in the ADDING state. In this case, the FSM should |
| * just go back to the NULL state. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_process_adding_timeout(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "Error: Received a timeout while in the %s state.\n", |
| acc_term_state_name_get(p_acc_term_inst->fsm_state)); |
| |
| |
| /* |
| * Send the indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(BCM_ERR_TIMEOUT, |
| (void *)&(p_acc_term_inst->current_acc_term_obj_info.hdr.hdr), |
| log_id_access_terminal); |
| |
| /* |
| * Go back to the previous state |
| */ |
| p_acc_term_inst->fsm_state = ACC_TERM_FSM_STATE_NULL; |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_FALSE); |
| |
| return ret; |
| |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM state processing a timeout that occurs |
| * when the FSM is in the REMOVING state. In this case, the FSM should |
| * just go back to the ADDED state. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_process_removing_timeout(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(INFO, log_id_access_terminal, |
| "Received a timeout while in the %s state. Going back to the ADDED state\n", |
| acc_term_state_name_get(p_acc_term_inst->fsm_state)); |
| |
| /* |
| * Go back to the previous state |
| */ |
| p_acc_term_inst->fsm_state = ACC_TERM_FSM_STATE_ADDED; |
| |
| return ret; |
| |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The function to process a |
| * message from one of the BAL apps for the specified interface |
| * |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| bcmos_errno process_interface_util_msg(void *msg) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| uint32_t interface_index = INVALID_INTERFACE_INDEX; |
| bal_util_msg_ind *ind_msg; |
| acc_term_interface *p_interface_inst; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == msg); |
| |
| ind_msg = (bal_util_msg_ind *)msg; |
| |
| /* |
| * NOTE: AUTO_IND messages are not processed in this function, |
| * so there is no need to consider them in this logic. |
| */ |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| " Received an interface IND message from BAL UTIL (%s)\n", |
| subsystem_str[bcmbal_sender_get(msg)]); |
| |
| if (BCM_ERR_OK == ind_msg->status) |
| { |
| /* first get the index to the interface array from port id/type */ |
| interface_index = bcmbal_port_type_and_id_to_interface_index(ind_msg->obj_key.if_key.intf_type, |
| ind_msg->obj_key.if_key.intf_id); |
| |
| if (interface_index >= INVALID_INTERFACE_INDEX) |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "INVALID port type/id (%s/%d) to interface index (%d)\n", |
| interface_type_str_get(ind_msg->obj_key.if_key.intf_type), |
| ind_msg->obj_key.if_key.intf_id, |
| interface_index); |
| |
| ret = BCM_ERR_PARM; |
| } |
| |
| p_interface_inst = &(access_terminal_get()->intf_info.interface[interface_index]); |
| |
| if(BCM_ERR_OK == ret) |
| { |
| /* Core calls Switch Utils to set the interface parameters using the applicable SDK call |
| * If a PON port is being set, then the corresponding direct connect switch port is also |
| * set along with it |
| */ |
| ret = sw_util_interface_set(p_interface_inst, |
| (p_interface_inst->api_req_int_obj_info.data.admin_state == BCMBAL_STATE_DOWN ? |
| BAL_UTIL_OPER_IF_DOWN : BAL_UTIL_OPER_IF_UP)); |
| |
| if (ret) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "sw_util_interface_set(() failed. rc=%s\n", bcmos_strerror(ret)); |
| |
| } |
| } |
| else |
| { |
| /* Error */ |
| BCM_LOG(ERROR, log_id_interface, |
| "Bad interface index: interface type/id (%s/%d) (status: %s)\n", |
| interface_type_str_get(ind_msg->obj_key.if_key.intf_type), |
| ind_msg->obj_key.if_key.intf_id, |
| bcmos_strerror(ind_msg->status)); |
| } |
| |
| |
| |
| if(BCM_ERR_OK == ret) |
| { |
| BCM_LOG(DEBUG, log_id_interface, |
| "Setting interface (%d) to %s\n", |
| interface_index, |
| (BCMBAL_STATE_UP == p_interface_inst->api_req_int_obj_info.data.admin_state) ? |
| "UP" : "DOWN"); |
| |
| |
| /* |
| * Interface SET function succeeded, so copy the API request into the |
| * current interface object. |
| */ |
| |
| bcmbal_interface_object_overlay_w_src_priority(&(p_interface_inst->current_int_obj_info),&(p_interface_inst->api_req_int_obj_info)); |
| |
| /* Set the status of the current interface that we just configured to the requested state (UP or DOWN) */ |
| BCMBAL_CFG_PROP_SET(&p_interface_inst->current_int_obj_info, |
| interface, |
| oper_status, |
| bcmbal_get_intf_oper_status_from_admin_state(p_interface_inst->api_req_int_obj_info.data.admin_state)); |
| |
| } |
| else |
| { |
| /* Error */ |
| BCM_LOG(ERROR, log_id_interface, |
| "Bad response from switch: Interface type/Id: %s/%d (status:%s) \n", |
| interface_type_str_get(ind_msg->obj_key.if_key.intf_type), |
| ind_msg->obj_key.if_key.intf_id, |
| bcmos_strerror(ind_msg->status)); |
| |
| } |
| } |
| else |
| { |
| /* Error */ |
| BCM_LOG(ERROR, log_id_interface, |
| "Bad interface indication from MAC (status:%s)\n", |
| bcmos_strerror(ind_msg->status)); |
| } |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_interface_inst->current_int_obj_info), BCMOS_FALSE); |
| |
| /* |
| * Send the indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| (void *)&(p_interface_inst->current_int_obj_info.hdr), |
| log_id_interface); |
| |
| return ret; |
| |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Access terminal FSM function which is executed when an error |
| * is encountered during FSM processing. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * @param msg Pointer to a BAL message (MAY BE NULL!) |
| * @param p_event Pointer to an access terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno acc_term_fsm_state_err(acc_term_inst *p_acc_term_inst, |
| void *msg, |
| acc_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_INVALID_OP; |
| |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "Error encountered processing FSM - BAD EVENT event:%s, state:%s\n", |
| acc_term_event_name_get(p_event->event_type), |
| acc_term_state_name_get(p_acc_term_inst->fsm_state)); |
| |
| return ret; |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function called by the core worker thread to process an |
| * access-terminal object message (SET, GET, CLEAR, STATS) received |
| * from the BAL Public API. |
| * |
| * @param msg_payload Pointer to a BAL message received from the |
| * BAL Public API. |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| bcmos_errno process_access_terminal_object(void *msg_payload) |
| { |
| |
| bcmos_errno ret = BCM_ERR_OK, rsp_ret = BCM_ERR_OK; |
| acc_term_inst *p_access_terminal_inst; |
| acc_term_fsm_event acc_term_event; |
| bcmbal_obj_msg_type oper_type; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == msg_payload); |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "Processing an access-terminal object\n"); |
| |
| do |
| { |
| /* |
| * Find or create the specified access terminal instance |
| */ |
| p_access_terminal_inst = access_terminal_get(); |
| |
| oper_type = ((bcmbal_access_terminal_cfg *)msg_payload)->hdr.hdr.type; |
| |
| /* If the state of the access-terminal is in flux, then reject the SET request */ |
| if(BCMBAL_OBJ_MSG_TYPE_SET == oper_type && |
| BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_access_terminal_inst->current_acc_term_obj_info))) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "The access-terminal is in-progress, SETs are not allowed\n"); |
| ret = BCM_ERR_IN_PROGRESS; |
| break; |
| } |
| |
| /* Copy the object in the message into local storage */ |
| memcpy(&p_access_terminal_inst->api_req_acc_term_obj_info, |
| msg_payload, |
| sizeof(p_access_terminal_inst->api_req_acc_term_obj_info)); |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "access_terminal admin state is: %s\n", |
| (BCMBAL_STATE_UP == p_access_terminal_inst->api_req_acc_term_obj_info.data.admin_state) ? |
| "UP" : "DOWN"); |
| |
| /* |
| * A message pointer is always passed inside the event structure. |
| */ |
| acc_term_event.msg = msg_payload; |
| |
| /* SET or GET or ...? */ |
| switch (oper_type) |
| { |
| case (BCMBAL_OBJ_MSG_TYPE_SET): |
| { |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "Processing a access-terminal SET REQ mgmt message\n"); |
| |
| /* |
| * Check if the mandatory access-terminal attributes have been set |
| */ |
| |
| do |
| { |
| |
| /* The admin state attribute is mandatory */ |
| if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(&p_access_terminal_inst->api_req_acc_term_obj_info, |
| access_terminal, |
| admin_state)) |
| { |
| ret = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| break; |
| } |
| |
| /*set iwf_mode from the global config parameters*/ |
| BCMBAL_CFG_PROP_SET(&p_access_terminal_inst->api_req_acc_term_obj_info, |
| access_terminal, |
| iwf_mode, |
| bcmbal_config_get()->iwf_mode); |
| |
| /* |
| * Perform the validation check(s) that the utils require |
| */ |
| if(BCM_ERR_OK != |
| (ret = mac_util_access_terminal_info_validate(&p_access_terminal_inst->api_req_acc_term_obj_info))) |
| { |
| break; |
| } |
| } |
| while(0); |
| |
| /* We respond to the BAL public API backend with a result. We always |
| * send a complete msg_payload back to the API, but the data portion |
| * of the object is only relevant when a GET or GET-STATS has been requested. |
| */ |
| rsp_ret = mgmt_msg_send_balapi_rsp(ret, |
| msg_payload, |
| oper_type, |
| log_id_access_terminal); |
| |
| if(BCM_ERR_OK != rsp_ret || BCM_ERR_OK != ret) |
| { |
| /* the mgmt_msg_send_balapi_rsp function above logs any errors that occur there */ |
| ret = (BCM_ERR_OK != rsp_ret) ? rsp_ret : ret; |
| break; |
| } |
| |
| /* Reflect the admin state of the access-terminal according to the commanded admin state */ |
| BCMBAL_CFG_PROP_SET(&p_access_terminal_inst->current_acc_term_obj_info, |
| access_terminal, |
| admin_state, |
| p_access_terminal_inst->api_req_acc_term_obj_info.data.admin_state); |
| |
| if(BCMBAL_STATE_UP == p_access_terminal_inst->api_req_acc_term_obj_info.data.admin_state) |
| { |
| |
| acc_term_event.event_type = ACC_TERM_FSM_EVENT_TYPE_ADMIN_UP; |
| } |
| else |
| { |
| acc_term_event.event_type = ACC_TERM_FSM_EVENT_TYPE_ADMIN_DN; |
| } |
| |
| /* |
| * Run the access terminal FSM to process this event |
| */ |
| ret = access_terminal_fsm_exec(p_access_terminal_inst, &acc_term_event); |
| break; |
| |
| } |
| case (BCMBAL_OBJ_MSG_TYPE_GET): |
| { |
| |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "Processing a access-terminal GET REQ mgmt message\n"); |
| |
| p_access_terminal_inst->current_acc_term_obj_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr; |
| *((bcmbal_access_terminal_cfg *)msg_payload) = p_access_terminal_inst->current_acc_term_obj_info; |
| |
| mgmt_msg_send_balapi_rsp(ret, |
| msg_payload, |
| oper_type, |
| log_id_access_terminal); |
| break; |
| |
| } |
| default: |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "Unsupported operation on access-terminal object (%d)\n", |
| bcmbal_msg_id_oper_get(msg_payload)); |
| |
| ret = BCM_ERR_NOT_SUPPORTED; |
| |
| /* We respond to the BAL public API backend with a result. We always |
| * send a complete msg_payload back to the API, but the data portion |
| * of the object is only relevant when a GET or GET-STATS has been requested. |
| */ |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_access_terminal); |
| |
| break; |
| } |
| } |
| }while(0); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to retrieve an access-terminal instance |
| * |
| * @returns acc_term_inst_t* A pointer to the found access-terminal instance, |
| * or NULL if one is not found. |
| *****************************************************************************/ |
| static acc_term_inst *access_terminal_get(void) |
| { |
| acc_term_inst *p_acc_term = (acc_term_inst *)NULL; |
| |
| p_acc_term = &single_access_terminal_instance; |
| |
| return p_acc_term; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to retrieve the status of the access-terminal |
| * |
| * |
| * @returns bcmbal_status |
| *****************************************************************************/ |
| bcmbal_status acc_term_status_get(void) |
| { |
| acc_term_inst *p_acc_term_inst; |
| |
| p_acc_term_inst = access_terminal_get(); |
| |
| return p_acc_term_inst->current_acc_term_obj_info.data.oper_status; |
| |
| } |
| |
| static bcmos_errno interface_tm_sched_set(bcmbal_interface_cfg *p_interface_info) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| tm_sched_inst *p_tm_sched_inst; |
| bcmbal_tm_sched_key tm_key; |
| switch(p_interface_info->key.intf_type) |
| { |
| case BCMBAL_INTF_TYPE_PON: |
| { |
| /*for active pon interface: |
| ds_tm should be define, - if it is set, validate sched exist and match direction (ds) |
| if not set - will create auto created tm */ |
| if(BCMBAL_CFG_PROP_IS_SET(p_interface_info,interface,ds_tm)) |
| { |
| tm_key.dir = BCMBAL_TM_SCHED_DIR_DS; |
| tm_key.id = p_interface_info->data.ds_tm; |
| p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE); |
| if (NULL == p_tm_sched_inst) |
| { |
| BCM_LOG(ERROR, log_id_interface, "there is no ds tm sched with id %d", tm_key.id); |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d", |
| p_interface_info->key.intf_id, tm_key.id); |
| break; |
| } |
| } |
| else /*auto created sched was removed and no other default sched was set*/ |
| { |
| BCM_LOG(ERROR, log_id_interface, "default tm node must be set! "); |
| ret = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| break; |
| } |
| /* us_tm is optional - if it is set, validate sched exist and match direction (us)*/ |
| if(BCMBAL_CFG_PROP_IS_SET(p_interface_info, interface, us_tm)) |
| { |
| tm_key.dir = BCMBAL_TM_SCHED_DIR_US; |
| tm_key.id = p_interface_info->data.us_tm; |
| p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE); |
| if (NULL == p_tm_sched_inst) |
| { |
| BCM_LOG(ERROR, log_id_interface, "there is no us tm sched with id %d", tm_key.id); |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d", |
| p_interface_info->key.intf_id, tm_key.id); |
| break; |
| } |
| } |
| |
| } |
| break; |
| |
| case BCMBAL_INTF_TYPE_NNI: |
| { |
| /*for active nni interface: |
| us_tm should be define, - |
| if it is set, validate sched exist and match direction (us) |
| if not set - will create auto created tm |
| */ |
| if(BCMBAL_CFG_PROP_IS_SET(p_interface_info, interface, us_tm)) |
| { |
| tm_key.dir = BCMBAL_TM_SCHED_DIR_US; |
| tm_key.id = p_interface_info->data.us_tm; |
| p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE); |
| if (NULL == p_tm_sched_inst) |
| { |
| BCM_LOG(ERROR, log_id_interface, "there is no us tm sched with id %d", tm_key.id); |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d", |
| p_interface_info->key.intf_id, tm_key.id); |
| break; |
| } |
| } |
| else /*auto created sched was removed and no other default sched was set*/ |
| { |
| BCM_LOG(ERROR, log_id_interface, "default tm node must be set! "); |
| break; |
| } |
| /* ds_tm is optional - if it is set, validate sched exist and match direction (ds)*/ |
| if(BCMBAL_CFG_PROP_IS_SET(p_interface_info, interface, ds_tm)) |
| { |
| tm_key.dir = BCMBAL_TM_SCHED_DIR_DS; |
| tm_key.id = p_interface_info->data.ds_tm; |
| p_tm_sched_inst = tm_sched_inst_get(tm_key, TM_SCHED_FLAG_ACTIVE); |
| if (NULL == p_tm_sched_inst) |
| { |
| BCM_LOG(ERROR, log_id_interface, "there is no ds tm sched with id %d", tm_key.id); |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| ret = bcmbal_tm_sched_set_interface_owner(p_interface_info->key, p_tm_sched_inst); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface, "could not set interface %d as owner of tm sched %d", |
| p_interface_info->key.intf_id, tm_key.id); |
| break; |
| } |
| } |
| } |
| break; |
| |
| default: |
| BCM_LOG(ERROR, log_id_interface, "Invalid intf type (%d) in interface key\n", |
| p_interface_info->key.intf_type); |
| ret = BCM_ERR_PARM; |
| } |
| return ret; |
| } |
| |
| bcmos_errno interface_tm_sched_unset(bcmbal_interface_key intf_key, bcmbal_tm_sched_key sched_key) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| acc_term_interface *p_acc_term_interface = bcmbal_interface_get(intf_key); |
| do |
| { |
| if(NULL == p_acc_term_interface) |
| { |
| BCM_LOG(ERROR, log_id_interface, "no such interface (id = %d dir = %s ) \n", |
| intf_key.intf_id, interface_type_str_get(intf_key.intf_type)); |
| ret = BCM_ERR_INTERNAL; |
| break; |
| } |
| if (BCMBAL_TM_SCHED_DIR_US == sched_key.dir) |
| { |
| BCMBAL_CFG_PROP_CLEAR(&(p_acc_term_interface->current_int_obj_info), interface, us_tm); |
| } |
| else |
| { |
| BCMBAL_CFG_PROP_CLEAR(&(p_acc_term_interface->current_int_obj_info), interface, ds_tm); |
| } |
| }while(0); |
| return ret; |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to process an interface object message |
| * (SET, GET, CLEAR, STATS) received from the BAL Public API. |
| * |
| * @param msg_payload Pointer to a BAL message received from the |
| * BAL Public API. |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| bcmos_errno process_interface_object(void *msg_payload) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| bcmbal_interface_cfg *p_intf_cfg = (bcmbal_interface_cfg *)msg_payload; |
| bcmbal_interface_key *p_intf_key; |
| acc_term_inst *p_access_terminal_inst; |
| |
| bcmbal_interface_cfg *p_api_req_interface_info; |
| bcmbal_interface_cfg *p_current_interface_info; |
| uint32_t interface_index = INVALID_INTERFACE_INDEX; |
| bcmbal_obj_msg_type oper_type; |
| |
| BCM_LOG(DEBUG, log_id_interface, |
| "Processing an interface object\n"); |
| |
| do |
| { |
| do |
| { |
| oper_type = p_intf_cfg->hdr.hdr.type; |
| |
| /* |
| * See if the access terminal is active |
| */ |
| p_access_terminal_inst = access_terminal_get(); |
| |
| if(NULL == p_access_terminal_inst) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "the access-terminal is not active\n"); |
| |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| /* If the state of the access-terminal is in flux, then reject the SET request */ |
| if(BCMBAL_OBJ_MSG_TYPE_SET == oper_type && |
| BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_access_terminal_inst->current_acc_term_obj_info))) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "The access-terminal is in-progress, SETs to an interface are not allowed\n"); |
| |
| ret = BCM_ERR_IN_PROGRESS; |
| break; |
| } |
| |
| /* |
| * Get the interface key from the message |
| */ |
| p_intf_key = &p_intf_cfg->key; |
| |
| if (p_intf_key->intf_type == BCMBAL_INTF_TYPE_PON) |
| { |
| if(p_intf_key->intf_id > NUM_SUPPORTED_SUBSCRIBER_INTERFACES) |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "out of range value (%d) detected in interface key for PON\n", p_intf_key->intf_id); |
| |
| ret = BCM_ERR_RANGE; |
| break; |
| } |
| } |
| /** @todo check the lower limit also */ |
| else if (p_intf_key->intf_type == BCMBAL_INTF_TYPE_NNI) |
| { |
| if( BCMOS_FALSE == bcm_topo_nni_is_valid(p_intf_key->intf_id)) |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "out of range value (%d) detected in interface key for NNI\n", p_intf_key->intf_id); |
| |
| ret = BCM_ERR_RANGE; |
| break; |
| } |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "Invalid intf type (%d) in interface key\n", p_intf_key->intf_type); |
| |
| ret = BCM_ERR_PARM; |
| break; |
| } |
| |
| /* |
| * Don't accept interface object references when the associated access-terminal is down |
| * |
| * Interfaces are not even instantiated internally until the access-terminal object to which |
| * they belong is instantiated. |
| */ |
| if(BCMBAL_STATE_DOWN == p_access_terminal_inst->current_acc_term_obj_info.data.admin_state) |
| { |
| BCM_LOG(INFO, log_id_interface, |
| "access terminal admin-state is DOWN\n"); |
| |
| ret = BCM_ERR_INVALID_OP; |
| break; |
| } |
| |
| /* Get the index to the interface array from port id/type */ |
| interface_index = bcmbal_port_type_and_id_to_interface_index (p_intf_key->intf_type, p_intf_key->intf_id); |
| if (interface_index >= INVALID_INTERFACE_INDEX) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "INVALID port type/id (%s/%d) to interface index (%d) for access terminal\n", |
| interface_type_str_get(p_intf_key->intf_type), p_intf_key->intf_id, interface_index); |
| |
| ret = BCM_ERR_PARM; |
| break; |
| } |
| |
| /* |
| * This is a pointer to the "API interface" structure |
| */ |
| p_api_req_interface_info = |
| &(p_access_terminal_inst->intf_info.interface[interface_index].api_req_int_obj_info); |
| |
| /* |
| * This is a pointer to the "current interface" structure |
| */ |
| p_current_interface_info = |
| &(p_access_terminal_inst->intf_info.interface[interface_index].current_int_obj_info); |
| |
| /* If the state of the interface is in flux, then reject the SET request */ |
| if(BCMBAL_OBJ_MSG_TYPE_SET == oper_type && |
| (BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(p_current_interface_info))) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "The interface is in-progress, SETs are not allowed\n"); |
| ret = BCM_ERR_IN_PROGRESS; |
| break; |
| } |
| |
| }while(0); |
| |
| if(BCM_ERR_OK != ret) |
| { |
| /* We respond to the BAL public API backend with a result. We always |
| * send a complete msg_payload back to the API, but the data portion |
| * of the object is only relevant when a GET or GET-STATS has been requested. |
| */ |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface); |
| break; |
| } |
| |
| /* |
| * Fill in the interface info SET data structure |
| */ |
| *p_api_req_interface_info = *p_intf_cfg; |
| |
| BCM_LOG(DEBUG, log_id_interface, |
| " interface object state from API message is: %d, intf_type: %s intf_id: %d\n", |
| p_api_req_interface_info->data.admin_state, |
| interface_type_str_get(p_api_req_interface_info->key.intf_type), |
| p_api_req_interface_info->key.intf_id); |
| |
| |
| /* SET or GET or ...? */ |
| switch (oper_type) |
| { |
| |
| case (BCMBAL_OBJ_MSG_TYPE_SET): |
| { |
| BCM_LOG(DEBUG, log_id_interface, |
| "Processing an interface SET REQ mgmt message\n"); |
| /*if sched is already set, can not change sched setting using set command, should first delete current sched*/ |
| if(BCMBAL_CFG_PROP_IS_SET(p_current_interface_info,interface,ds_tm) |
| && BCMBAL_CFG_PROP_IS_SET(p_api_req_interface_info,interface,ds_tm)) |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "ds_tm %d is already set at interface, it should be first cleared in order to be replaced \n", |
| p_current_interface_info->data.ds_tm); |
| ret = BCM_ERR_ALREADY; |
| break; |
| } |
| if(BCMBAL_CFG_PROP_IS_SET(p_current_interface_info,interface,us_tm) |
| && BCMBAL_CFG_PROP_IS_SET(p_api_req_interface_info,interface,us_tm)) |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "us_tm %d is already set at interface, it should be first cleared in order to be replaced \n", |
| p_current_interface_info->data.us_tm); |
| ret = BCM_ERR_ALREADY; |
| break; |
| } |
| /* We respond to the BAL public API backend with a result. We always |
| * send a complete msg_payload back to the API, but the data portion |
| * of the object is only relevant when a GET or GET-STATS has been requested. |
| */ |
| ret = mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface); |
| |
| if(BCM_ERR_OK != ret) |
| { |
| break; |
| } |
| |
| /* If this interface is already up, then just return OK */ |
| if(BCMBAL_STATE_UP == p_api_req_interface_info->data.admin_state) |
| { |
| if(BCMBAL_STATUS_UP == p_current_interface_info->data.oper_status) |
| { |
| BCM_LOG(DEBUG, log_id_interface, |
| "=====> Received an interface UP for an already UP interface, returning OK\n"); |
| break; |
| } |
| |
| /*validate and set the interface' tm sched*/ |
| bcmbal_interface_object_overlay_w_dst_priority(p_api_req_interface_info,p_current_interface_info); |
| ret = interface_tm_sched_set(p_api_req_interface_info); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface,"Could not set the interface tm sched\n"); |
| break; |
| } |
| interface_admin_up_start(&(p_access_terminal_inst->intf_info.interface[interface_index]), |
| msg_payload); |
| } |
| else |
| { |
| if(BCMBAL_STATUS_DOWN == p_current_interface_info->data.oper_status) |
| { |
| BCM_LOG(DEBUG, log_id_interface, |
| "=====> Received an interface DOWN for an already DOWN interface, returning OK\n"); |
| |
| break; |
| } |
| |
| interface_admin_dn_start(&(p_access_terminal_inst->intf_info.interface[interface_index]), |
| msg_payload); |
| |
| } |
| |
| break; |
| |
| } |
| case (BCMBAL_OBJ_MSG_TYPE_GET): |
| { |
| |
| BCM_LOG(DEBUG, log_id_interface, |
| "Processing a interface GET REQ mgmt message\n"); |
| |
| /* We respond to the BAL public API backend with a result. We always |
| * send a complete msg_payload back to the API, but the data portion |
| * of the object is only relevant when a GET or GET-STATS has been requested. |
| */ |
| p_current_interface_info->hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr; |
| |
| bcmbal_sub_id_list_u16 sub_term_id_list = {}; |
| |
| BCMBAL_CFG_PROP_CLEAR(p_current_interface_info, |
| interface, |
| sub_term_id_list); |
| |
| /* If the user requested the list of sub_term_ids for this interface, |
| * and this is a PON interface, then return the list. |
| */ |
| if(BCMBAL_CFG_PROP_IS_SET(p_api_req_interface_info, |
| interface, |
| sub_term_id_list)) |
| { |
| if(BCMBAL_INTF_TYPE_PON == p_current_interface_info->key.intf_type) |
| { |
| |
| sub_term_id_list_fill(interface_index, &sub_term_id_list); |
| |
| /* NOTE: The returned list may be empty */ |
| BCMBAL_CFG_PROP_SET(p_current_interface_info, |
| interface, |
| sub_term_id_list, |
| sub_term_id_list); |
| |
| } |
| } |
| |
| *((bcmbal_interface_cfg *)msg_payload) = *p_current_interface_info; |
| |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface); |
| |
| /* Free the temporary list if it was used */ |
| if(sub_term_id_list.val) |
| { |
| bcmos_free(sub_term_id_list.val); |
| } |
| |
| break; |
| } |
| default: |
| { |
| BCM_LOG(ERROR, log_id_interface, |
| "Unsupported operation on interface object (%d)\n", |
| bcmbal_msg_id_oper_get(msg_payload)); |
| |
| ret = BCM_ERR_NOT_SUPPORTED; |
| |
| /* We respond to the BAL public API backend with a result. We always |
| * send a complete msg_payload back to the API, but the data portion |
| * of the object is only relevant when a GET or GET-STATS has been requested. |
| */ |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_interface); |
| break; |
| } |
| |
| } |
| |
| }while (0); |
| |
| return ret; |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function called to initialize a single access-terminal instance. |
| * NOTE: This is called once on startup and NOT for each FSM instance. |
| * |
| * @param p_acc_term_inst Pointer to an access terminal instance |
| * |
| * @returns void |
| *****************************************************************************/ |
| static void initialize_access_terminal_instance_config(acc_term_inst *p_acc_term_inst) |
| { |
| int ii; |
| int intf_id; |
| bcmos_errno ret; |
| |
| BUG_ON(NULL == p_acc_term_inst); |
| |
| p_acc_term_inst->current_acc_term_obj_info.key.access_term_id = 0; |
| |
| BCMBAL_CFG_INIT(&p_acc_term_inst->current_acc_term_obj_info, |
| access_terminal, |
| p_acc_term_inst->current_acc_term_obj_info.key); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info, |
| access_terminal, |
| admin_state, |
| BCMBAL_STATE_DOWN); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->current_acc_term_obj_info, |
| access_terminal, |
| oper_status, |
| BCMBAL_STATUS_DOWN); |
| |
| BCMBAL_PROP_SET_PRESENT(&p_acc_term_inst->current_acc_term_obj_info, |
| access_terminal, |
| _cfg, |
| iwf_mode); |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->current_acc_term_obj_info), BCMOS_FALSE); |
| |
| { |
| bcmbal_interface_key key; |
| |
| intf_id = 0; /* reset the port id to the starting id value for the PON interfaces */ |
| |
| key.intf_type = BCMBAL_INTF_TYPE_PON; |
| |
| for(ii=0; ii<NUM_SUPPORTED_SUBSCRIBER_INTERFACES; ii++) |
| { |
| |
| key.intf_id = intf_id; |
| |
| p_acc_term_inst->intf_info.interface[ii].num_sub_terms_on_int = 0; |
| TAILQ_INIT(&p_acc_term_inst->intf_info.interface[ii].sub_term_id_list); |
| |
| BCMBAL_CFG_INIT(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info, |
| interface, |
| key); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info, |
| interface, |
| admin_state, |
| BCMBAL_STATE_DOWN); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info, |
| interface, |
| oper_status, |
| BCMBAL_STATUS_DOWN); |
| |
| ret = bcmbal_tm_sched_interface_tm_auto_create(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface, "could not set an auto - create a tm sched for pon if %d", intf_id); |
| break; |
| } |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->intf_info.interface[ii].current_int_obj_info), BCMOS_FALSE); |
| |
| intf_id++; |
| } |
| |
| intf_id = 0; /* reset the port id to the starting id value for the NNI interfaces */ |
| |
| key.intf_type = BCMBAL_INTF_TYPE_NNI; |
| |
| for(ii=NUM_SUPPORTED_SUBSCRIBER_INTERFACES; ii<(NUM_SUPPORTED_SUBSCRIBER_INTERFACES + bal_config_params.num_nni_ports); ii++) |
| { |
| |
| key.intf_id = intf_id; |
| |
| BCMBAL_CFG_INIT(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info, |
| interface, |
| key); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info, |
| interface, |
| admin_state, |
| BCMBAL_STATE_UP); |
| |
| BCMBAL_CFG_PROP_SET(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info, |
| interface, |
| oper_status, |
| BCMBAL_STATUS_UP); |
| |
| |
| ret = bcmbal_tm_sched_interface_tm_auto_create(&p_acc_term_inst->intf_info.interface[ii].current_int_obj_info); |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_interface, "could not set an auto - create a tm sched for nni if %d", intf_id); |
| break; |
| } |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_acc_term_inst->intf_info.interface[ii].current_int_obj_info), BCMOS_FALSE); |
| |
| intf_id++; |
| } |
| } |
| } |
| |
| bcmos_errno bcmbal_interface_sub_term_list_entry_add(bcmbal_subscriber_terminal_key sub_term_key) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| acc_term_inst *p_access_terminal_inst; |
| sub_term_id_entry *current_entry; |
| acc_term_interface *p_interface; |
| |
| p_access_terminal_inst = access_terminal_get(); |
| |
| do |
| { |
| /* |
| * If the specified access terminal is not active then it's interfaces are down. |
| */ |
| if(NULL == p_access_terminal_inst) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "no such ACTIVE access terminal\n"); |
| ret = BCM_ERR_STATE; |
| break; |
| } |
| |
| p_interface = &p_access_terminal_inst->intf_info.interface[sub_term_key.intf_id]; |
| |
| /* Check if the id is already on the list before adding it */ |
| TAILQ_FOREACH(current_entry, |
| &p_interface->sub_term_id_list, |
| next) |
| { |
| if(current_entry->sub_term_id == sub_term_key.sub_term_id) |
| { |
| return BCM_ERR_ALREADY; |
| } |
| } |
| |
| /* Get a new entry and configure it */ |
| current_entry = bcmos_calloc(sizeof(sub_term_id_entry)); |
| |
| if (NULL == current_entry) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "No memory available\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| current_entry->sub_term_id = sub_term_key.sub_term_id; |
| |
| BCM_LOG(INFO, log_id_access_terminal, |
| "adding sub_term id %u to interface %u\n", sub_term_key.sub_term_id, sub_term_key.intf_id); |
| |
| /* Save the entry on the list of subscriber-terminal ids on this interface */ |
| TAILQ_INSERT_TAIL(&p_interface->sub_term_id_list, |
| current_entry, next); |
| |
| (p_interface->num_sub_terms_on_int)++; |
| |
| } while (0); |
| |
| return ret; |
| } |
| |
| bcmos_errno bcmbal_interface_sub_term_list_entry_remove(bcmbal_subscriber_terminal_key sub_term_key) |
| { |
| bcmos_errno ret = BCM_ERR_NOENT; |
| acc_term_inst *p_access_terminal_inst; |
| acc_term_interface *p_interface; |
| sub_term_id_entry *current_entry, *p_temp_entry; |
| |
| do |
| { |
| p_access_terminal_inst = access_terminal_get(); |
| |
| /* |
| * If the specified access terminal is not active then it's interfaces are down. |
| */ |
| if(NULL == p_access_terminal_inst) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "no such ACTIVE access terminal\n"); |
| ret = BCM_ERR_STATE; |
| break; |
| } |
| |
| p_interface = &p_access_terminal_inst->intf_info.interface[sub_term_key.intf_id]; |
| |
| /* Check if the id is on the list */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &p_interface->sub_term_id_list, |
| next, |
| p_temp_entry) |
| { |
| if(current_entry->sub_term_id == sub_term_key.sub_term_id) |
| { |
| /* Remove it from the list of subscriber-terminal ids on this interface */ |
| TAILQ_REMOVE(&p_interface->sub_term_id_list, |
| current_entry, next); |
| |
| bcmos_free(current_entry); |
| |
| (p_interface->num_sub_terms_on_int)--; |
| |
| ret = BCM_ERR_OK; |
| break; |
| |
| } |
| } |
| } while (0); |
| |
| return ret; |
| } |
| |
| static bcmos_errno sub_term_id_list_fill(uint32_t interface_index, |
| bcmbal_sub_id_list_u16 *sub_term_id_list) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| acc_term_inst *p_acc_term_inst; |
| sub_term_id_entry *current_entry = NULL; |
| int ii = 0; |
| |
| do |
| { |
| /* |
| * See if the access-terminal is active |
| */ |
| p_acc_term_inst = access_terminal_get(); |
| |
| /* |
| * If the specified access terminal is not active then it's interfaces are down. |
| */ |
| if(NULL == p_acc_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "no such ACTIVE access terminal\n"); |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| /* Traverse the list of sub_term_ids recorded and fill in the list to be returned */ |
| sub_term_id_list->len = p_acc_term_inst->intf_info.interface[interface_index].num_sub_terms_on_int; |
| sub_term_id_list->val = bcmos_calloc(sizeof(bcmbal_sub_id) * sub_term_id_list->len); |
| |
| if (NULL == sub_term_id_list->val) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "No memory available\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| TAILQ_FOREACH(current_entry, |
| &p_acc_term_inst->intf_info.interface[interface_index].sub_term_id_list, |
| next) |
| { |
| BCM_LOG(DEBUG, log_id_access_terminal, |
| "adding sub_term_id %u to response at array location %u\n", |
| current_entry->sub_term_id, |
| ii); |
| sub_term_id_list->val[ii++] = current_entry->sub_term_id; |
| } |
| |
| } while (0); |
| |
| return ret; |
| } |
| |
| bcmos_errno bcmbal_interface_tm_get(bcmbal_interface_key key, bcmbal_tm_sched_id *id) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| acc_term_inst *p_acc_term_inst; |
| uint32_t interface_index = INVALID_INTERFACE_INDEX; |
| |
| do |
| { |
| /* See if the access-terminal is active */ |
| p_acc_term_inst = access_terminal_get(); |
| |
| /* If the specified access terminal is not active then it's interfaces are down. */ |
| if(NULL == p_acc_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal,"no such ACTIVE access terminal\n"); |
| ret = BCM_ERR_NOT_CONNECTED; |
| break; |
| } |
| |
| /* If the specified access terminal is down, then it's interfaces are down. */ |
| if(BCMBAL_STATE_UP != p_acc_term_inst->current_acc_term_obj_info.data.admin_state) |
| { |
| ret = BCM_ERR_NOT_CONNECTED; |
| break; |
| } |
| |
| /* first get the index to the interface array from port id/type */ |
| interface_index = bcmbal_port_type_and_id_to_interface_index (key.intf_type, key.intf_id); |
| if (interface_index >= INVALID_INTERFACE_INDEX) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal,"INVALID port type/id (%s/%d) to interface index (%d)\n", |
| interface_type_str_get(key.intf_type), key.intf_id, interface_index); |
| ret = BCM_ERR_INTERNAL; |
| break; |
| } |
| /* Retrieve the relevany default tm sched of the interface */ |
| if (BCMBAL_INTF_TYPE_NNI == key.intf_type) |
| { |
| *id = p_acc_term_inst->intf_info.interface[interface_index].current_int_obj_info.data.us_tm; |
| } |
| else /*BCMBAL_INTF_TYPE_PON */ |
| { |
| *id = p_acc_term_inst->intf_info.interface[interface_index].current_int_obj_info.data.ds_tm; |
| } |
| }while(0); |
| |
| return ret; |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function that returns the status of the specified interface object |
| * |
| * @param key An interface instance key |
| * |
| * @returns bcmbal_state |
| *****************************************************************************/ |
| bcmbal_status bcmbal_interface_status_get(bcmbal_interface_key key) |
| { |
| bcmbal_state intf_status = BCMBAL_STATUS_DOWN; |
| acc_term_interface *p_acc_term_interface = bcmbal_interface_get(key); |
| |
| if(NULL == p_acc_term_interface) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal,"no such interface\n"); |
| } |
| else |
| { |
| intf_status = p_acc_term_interface->current_int_obj_info.data.oper_status; |
| } |
| return intf_status; |
| } |
| /*****************************************************************************/ |
| /** |
| * @brief A function that returns the interface object |
| * |
| * @param key An interface instance key |
| * |
| * @returns acc_term_interface *p_acc_term_interface a pointer to the interface object |
| *****************************************************************************/ |
| static acc_term_interface * bcmbal_interface_get(bcmbal_interface_key key) |
| { |
| acc_term_inst *p_acc_term_inst = NULL; |
| acc_term_interface *p_acc_term_interface = NULL; |
| uint32_t interface_index = INVALID_INTERFACE_INDEX; |
| |
| do |
| { |
| /* |
| * See if the access-terminal is active |
| */ |
| p_acc_term_inst = access_terminal_get(); |
| |
| |
| /* |
| * If the specified access terminal is not active then it's interfaces are down. |
| */ |
| if(NULL == p_acc_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "no such ACTIVE access terminal\n"); |
| break; |
| } |
| |
| /* |
| * Retrieve the interface |
| */ |
| /* first get the index to the interface array from port id/type */ |
| interface_index = bcmbal_port_type_and_id_to_interface_index (key.intf_type, key.intf_id); |
| if (interface_index >= INVALID_INTERFACE_INDEX) |
| { |
| BCM_LOG(ERROR, log_id_access_terminal, |
| "INVALID port type/id (%s/%d) to interface index (%d)\n", |
| interface_type_str_get(key.intf_type), key.intf_id, interface_index); |
| break; |
| } |
| p_acc_term_interface = &(p_acc_term_inst->intf_info.interface[interface_index]); |
| |
| }while(0); |
| |
| |
| return p_acc_term_interface; |
| } |
| |
| static char *interface_type_str_get(bcmbal_intf_type intf_type) |
| { |
| return intf_type == BCMBAL_INTF_TYPE_NNI ? "NNI" : |
| intf_type == BCMBAL_INTF_TYPE_PON ? "PON" : "UNKNOWN TYPE"; |
| } |
| /*@}*/ |