| /****************************************************************************** |
| * |
| * <: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 sub_term_fsm.c |
| * @brief Code to support the BAL subscriber-terminal FSM |
| * |
| * @addtogroup sub_terminal |
| * |
| */ |
| |
| /*@{*/ |
| |
| #include <bcmos_system.h> |
| #include <bal_msg.h> |
| #include <bal_osmsg.h> |
| #include "bal_worker.h" |
| #include "bal_mac_util.h" |
| #include "bal_switch_util.h" |
| #include "sub_term_fsm.h" |
| #include "tm_sched_fsm.h" |
| |
| #include <bal_objs.h> |
| #include <fsm_common.h> |
| |
| #ifdef ENABLE_LOG |
| #include <bcm_dev_log.h> |
| |
| /* |
| * @brief Logging device id for the subscriber-terminal |
| */ |
| static dev_log_id log_id_sub_term; |
| #endif |
| |
| /* local function declarations */ |
| |
| static bcmos_errno sub_term_fsm_admin_up_start(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_admin_up_error(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_admin_dn_start(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_admin_dn_ok(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_admin_dn_error(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_removing_start(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_ignore_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| |
| static bcmos_errno sub_term_fsm_removing_process_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_removing_process_util_auto_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_configuring_process_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_null_process_util_auto_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_configured_process_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_configuring_process_util_auto_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_state_err(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_fsm_exec(sub_term_inst *p_sub_term_inst, sub_term_fsm_event *p_event); |
| |
| static bcmos_errno sub_term_free_by_entry(sub_term_inst *p_entry); |
| |
| |
| static bcmos_errno agg_port_id_list_fill(sub_term_inst *p_sub_term_inst, |
| bcmbal_aggregation_port_id_list_u8 *agg_port_id_list); |
| |
| static bcmos_errno svc_port_id_list_fill(sub_term_inst *p_sub_term_inst, |
| bcmbal_service_port_id_list_u8 *svc_port_id_list); |
| |
| static bcmos_errno bcmbal_sub_term_tm_scheds_set(const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg); |
| |
| /* |
| *@brief Global sub_term fsm context data structure |
| */ |
| static sub_term_fsm_ctx g_sub_term_fsm_sub_term_list_ctx; |
| |
| /* |
| * Macros for sub_term ctx access |
| */ |
| #define SUB_TERM_FSM_SUB_TERM_LIST_CTX (g_sub_term_fsm_sub_term_list_ctx) |
| #define SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR (&g_sub_term_fsm_sub_term_list_ctx) |
| |
| /* |
| * @brief The definition of a sub_term state processing function |
| */ |
| typedef bcmos_errno (* sub_term_fsm_state_processor)(sub_term_inst *, void *, sub_term_fsm_event *); |
| |
| /* |
| * @brief The Subscriber Terminal FSM state processing array |
| */ |
| static sub_term_fsm_state_processor sub_term_states[SUB_TERM_FSM_STATE__NUM_OF][SUB_TERM_FSM_EVENT_TYPE__NUM_OF] = |
| { |
| |
| [SUB_TERM_FSM_STATE_NULL] = |
| { |
| /* |
| * Next state: CONFIGURING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_start, |
| |
| /* |
| * Next state: NULL |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_ok, |
| |
| /* |
| * Next state: NULL |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_ignore_util_msg, |
| |
| /* |
| * Next state: NULL |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_null_process_util_auto_msg, |
| }, |
| |
| [SUB_TERM_FSM_STATE_CONFIGURING] = |
| { |
| /* |
| * Next state: CONFIGURING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_error, |
| |
| /* |
| * Next state: CONFIGURING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_error, |
| |
| /* |
| * Next state: REMOVING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_REMOVE] = sub_term_fsm_removing_start, |
| |
| /* |
| * Next state: CONFIGURING | CONFIGURED |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_configuring_process_util_msg, |
| |
| /* |
| * Next state: CONFIGURING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_configuring_process_util_auto_msg, |
| |
| }, |
| |
| [SUB_TERM_FSM_STATE_CONFIGURED] = |
| { |
| /* |
| * Next state: CONFIGURED |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_start, |
| |
| /* |
| * Next state: CONFIGURING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_start, |
| |
| /* |
| * Next state: REMOVING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_REMOVE] = sub_term_fsm_removing_start, |
| |
| /* |
| * Next state: CONFIGURING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_configured_process_util_msg, |
| |
| /* |
| * Next state: CONFIGURED |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_ignore_util_msg, |
| |
| }, |
| |
| [SUB_TERM_FSM_STATE_REMOVING] = |
| { |
| /* |
| * Next state: REMOVING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP] = sub_term_fsm_admin_up_error, |
| |
| /* |
| * Next state: REMOVING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN] = sub_term_fsm_admin_dn_error, |
| |
| /* |
| * Next state: REMOVING | NULL |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG] = sub_term_fsm_removing_process_util_msg, |
| |
| /* |
| * Next state: REMOVING |
| */ |
| [SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG] = sub_term_fsm_removing_process_util_auto_msg, |
| }, |
| }; |
| |
| static char *state_name_str[] = |
| { |
| "SUB_TERM_FSM_STATE_NULL", |
| "SUB_TERM_FSM_STATE_CONFIGURING", |
| "SUB_TERM_FSM_STATE_CONFIGURED", |
| "SUB_TERM_FSM_STATE_REMOVING", |
| }; |
| |
| /* Ensure that the name array size matches the associated enum */ |
| BAL_STATIC_ASSERT (SUB_TERM_FSM_STATE__LAST == (sizeof (state_name_str) / sizeof (char *)), sub_term_fsm_state); |
| |
| static char *sub_term_state_name_get(sub_term_fsm_state state) |
| { |
| if(state < SUB_TERM_FSM_STATE__LAST) |
| { |
| return state_name_str[state]; |
| } |
| else |
| { |
| return "SUB_TERM_UNKNOWN"; |
| } |
| } |
| |
| static char *event_name_str[] = |
| { |
| "SUB_TERM_FSM_ADMIN_UP_EVENT", |
| "SUB_TERM_FSM_ADMIN_DN_EVENT", |
| "SUB_TERM_FSM_REMOVE_EVENT", |
| "SUB_TERM_FSM_UTIL_MSG_EVENT", |
| "SUB_TERM_FSM_UTIL_AUTO_IND_EVENT", |
| }; |
| |
| /* Ensure that the name array size matches the associated enum */ |
| BAL_STATIC_ASSERT (SUB_TERM_FSM_EVENT_TYPE__LAST == (sizeof (event_name_str) / sizeof (char *)), sub_term_fsm_event_type); |
| |
| static char *sub_term_event_name_get(sub_term_fsm_event_type event) |
| { |
| if(event < SUB_TERM_FSM_EVENT_TYPE__LAST) |
| { |
| return event_name_str[event]; |
| } |
| else |
| { |
| return "SUB_TERM_EVT_UNKNOWN"; |
| } |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to initialize the current sub_term_info object of the |
| * supplied entry. |
| * |
| * @param p_entry A pointer to the entry to be initialized |
| * |
| * |
| * @returns void |
| *****************************************************************************/ |
| static void sub_term_inst_entry_obj_init(sub_term_inst *p_entry) |
| { |
| bcmbal_subscriber_terminal_key key = { .sub_term_id = 0, .intf_id = 0 }; |
| BCMBAL_CFG_INIT(&p_entry->current_sub_term_info, |
| subscriber_terminal, |
| key); |
| |
| BCMBAL_CFG_PROP_SET(&p_entry->current_sub_term_info, |
| subscriber_terminal, admin_state, BCMBAL_STATE_DOWN); |
| |
| BCMBAL_CFG_PROP_SET(&p_entry->current_sub_term_info, |
| subscriber_terminal, oper_status, BCMBAL_STATUS_NOT_PRESENT); |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_entry->current_sub_term_info), BCMOS_FALSE); |
| |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function called to initialize the subscriber-terminal FSM |
| * infrastructure. |
| * |
| * NOTE: This is called once on startup and NOT for each FSM instance. |
| * |
| * @returns void |
| *****************************************************************************/ |
| bcmos_errno sub_term_fsm_init(void) |
| { |
| int ii; |
| sub_term_inst *new_entry; |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| #ifdef ENABLE_LOG |
| log_id_sub_term = bcm_dev_log_id_register("SUB_TERM", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| BUG_ON(log_id_sub_term == DEV_LOG_INVALID_ID); |
| #endif |
| |
| /* Initialize all of the sub_term queues */ |
| TAILQ_INIT(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list); |
| TAILQ_INIT(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list); |
| |
| /* Populate the free list with it's set of sub_term instance entries */ |
| for(ii=0; ii<NUM_SUPPORTED_SUB_TERMS; ii++) |
| { |
| |
| new_entry = bcmos_calloc(sizeof(sub_term_inst)); |
| |
| if (NULL == new_entry) |
| { |
| BCM_LOG(FATAL, log_id_sub_term, |
| "Failed to initialize the sub_term free list - FATAL\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| /* And add it to the free list */ |
| sub_term_free_by_entry(new_entry); |
| |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to un-initialize the subscriber-terminal FSM infrastructure. |
| * |
| * NOTE: This is called once on shutdown and NOT for each FSM instance. |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| bcmos_errno sub_term_fsm_finish(void) |
| { |
| |
| sub_term_inst *current_entry, *p_temp_entry; |
| agg_port_id_entry *agg_port_entry; |
| svc_port_id_entry *svc_port_entry; |
| |
| /* Free all the entries on the active list */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list, |
| sub_term_inst_next, |
| p_temp_entry) |
| { |
| /* free the aggregation port list */ |
| TAILQ_FOREACH(agg_port_entry, |
| ¤t_entry->agg_port_id_list, |
| next) |
| { |
| |
| bcmos_free(agg_port_entry); |
| } |
| |
| /* free the service port list */ |
| TAILQ_FOREACH(svc_port_entry, |
| ¤t_entry->svc_port_id_list, |
| next) |
| { |
| bcmos_free(svc_port_entry); |
| } |
| |
| /* Remove it from the active list */ |
| TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list, |
| current_entry, sub_term_inst_next); |
| |
| bcmos_free(current_entry); |
| |
| } |
| |
| /* Free all the entries on the free list */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list, |
| sub_term_inst_next, |
| p_temp_entry) |
| { |
| /* Remove it from the active list */ |
| TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list, |
| current_entry, sub_term_inst_next); |
| |
| bcmos_free(current_entry); |
| |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing executive function |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_exec(sub_term_inst *p_sub_term_inst, sub_term_fsm_event *p_event) |
| { |
| |
| bcmos_errno ret = BCM_ERR_OK; |
| sub_term_fsm_state pre_state; |
| sub_term_fsm_state fsm_state; |
| sub_term_fsm_state_processor sub_term_state_processor; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_event); |
| |
| /* Record the present state for debug printing |
| */ |
| pre_state = (NULL == p_sub_term_inst) ? SUB_TERM_FSM_STATE_NULL : p_sub_term_inst->fsm_state; |
| |
| /* |
| * Get the state processing function |
| */ |
| sub_term_state_processor = sub_term_states[pre_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 (sub_term_state_processor) |
| { |
| ret = sub_term_state_processor(p_sub_term_inst, p_event->msg, p_event); |
| } else |
| { |
| sub_term_fsm_state_err(p_sub_term_inst, p_event->msg, p_event); |
| } |
| |
| /* And get the new state for debug printing */ |
| fsm_state = (NULL == p_sub_term_inst) ? SUB_TERM_FSM_STATE_NULL : p_sub_term_inst->fsm_state; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "*** Event %s, State: %s --> %s\n", |
| sub_term_event_name_get(p_event->event_type), |
| sub_term_state_name_get(pre_state), sub_term_state_name_get(fsm_state)); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function called by the core worker thread to process an |
| * subscriber-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_subscriber_terminal_object(void *msg_payload) |
| { |
| |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| bcmbal_subscriber_terminal_cfg *p_sub_term_cfg = (bcmbal_subscriber_terminal_cfg *)msg_payload; |
| sub_term_inst *p_sub_term_inst; |
| sub_term_fsm_event fsm_event; |
| bcmbal_subscriber_terminal_key *sub_term_key; |
| bcmbal_obj_msg_type oper_type; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == msg_payload); |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "Processing a sub_term object\n"); |
| |
| sub_term_key = &p_sub_term_cfg->key; |
| |
| oper_type = p_sub_term_cfg->hdr.hdr.type; |
| |
| /* |
| * A message pointer may be passed inside the event structure. |
| */ |
| fsm_event.msg = msg_payload; |
| |
| /* SET or GET or CLEAR ? */ |
| switch (oper_type) |
| { |
| case (BCMBAL_OBJ_MSG_TYPE_SET): |
| { |
| bcmos_bool b_generate_event = BCMOS_FALSE; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "Processing a sub_term SET REQ mgmt message\n"); |
| |
| /* |
| * Find or create the specified sub_term instance |
| */ |
| p_sub_term_inst = sub_term_inst_get(sub_term_key, SUB_TERM_FLAG_ANY); |
| |
| do |
| { |
| |
| if(NULL == p_sub_term_inst) |
| { |
| /* This is a fatal error condition |
| */ |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Specified sub_term not found. No further processing\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| /* If the state of this sub_term is in flux, then reject the SET request */ |
| if(BCMOS_TRUE == BCMBAL_OBJ_IN_PROGRESS_GET(&(p_sub_term_inst->current_sub_term_info))) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "The subscriber_terminal is in-progress, SETs are not allowed\n"); |
| ret = BCM_ERR_IN_PROGRESS; |
| break; |
| } |
| |
| if(BCM_ERR_OK != (ret = bcmbal_sub_term_tm_scheds_set(p_sub_term_cfg))) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "could not set subscriber terminal as owner of specified tm scheds\n"); |
| ret = BCM_ERR_PARM; |
| |
| } |
| |
| /* |
| * Fill in the local sub_term instance API request data structure |
| */ |
| p_sub_term_inst->api_req_sub_term_info = *p_sub_term_cfg; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "sub_term admin state is: %s\n", |
| (BCMBAL_STATE_UP == p_sub_term_inst->api_req_sub_term_info.data.admin_state) ? "UP" : "DOWN"); |
| |
| |
| /* If there's no state change, then we're done */ |
| if(p_sub_term_inst->current_sub_term_info.data.admin_state == |
| p_sub_term_inst->api_req_sub_term_info.data.admin_state) |
| { |
| break; |
| } |
| |
| /* For subscriber terminals that have already been configured and then made dormant, merge the |
| * requested data with the current data, and this is the new request. |
| */ |
| if(BCMBAL_STATUS_DOWN == p_sub_term_inst->current_sub_term_info.data.oper_status) |
| { |
| |
| bcmbal_sub_term_object_overlay_w_dst_priority(&p_sub_term_inst->api_req_sub_term_info, |
| &p_sub_term_inst->current_sub_term_info); |
| } |
| |
| /* |
| * Check if the mandatory subscriber terminal attributes have been set, and range check where |
| * applicable. |
| */ |
| |
| |
| /* The admin state attribute is mandatory */ |
| if(BCMOS_FALSE == BCMBAL_CFG_PROP_IS_SET(&p_sub_term_inst->api_req_sub_term_info, |
| subscriber_terminal, |
| admin_state)) |
| { |
| ret = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| break; |
| } |
| |
| /* |
| * Perform the validation check(s) that the utils require |
| */ |
| if(BCM_ERR_OK != |
| (ret = mac_util_subscriber_terminal_info_validate(&p_sub_term_inst->api_req_sub_term_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. |
| */ |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term); |
| |
| if(BCM_ERR_OK != ret) |
| { |
| break; |
| } |
| |
| /* |
| * Initial checks complete. Process the request |
| */ |
| |
| if((BCMBAL_STATE_UP == p_sub_term_inst->api_req_sub_term_info.data.admin_state) |
| && (BCMBAL_STATE_UP != p_sub_term_inst->current_sub_term_info.data.admin_state)) |
| { |
| BCMBAL_CFG_PROP_SET(&p_sub_term_inst->api_req_sub_term_info, |
| subscriber_terminal, |
| svc_port_id, |
| sub_term_key->sub_term_id); |
| |
| p_sub_term_inst->api_req_sub_term_info.data.admin_state = BCMBAL_STATE_UP; |
| |
| /* Set the expected state of the oper_status upon success */ |
| p_sub_term_inst->api_req_sub_term_info.data.oper_status = BCMBAL_STATUS_UP; |
| |
| fsm_event.event_type = SUB_TERM_FSM_EVENT_TYPE_ADMIN_UP; |
| b_generate_event = BCMOS_TRUE; |
| |
| BCM_LOG(INFO, log_id_sub_term, |
| "***Using GEM %d for subscriber terminal OMCI channel\n", |
| p_sub_term_inst->api_req_sub_term_info.data.svc_port_id); |
| |
| } |
| else if((BCMBAL_STATE_DOWN == p_sub_term_inst->api_req_sub_term_info.data.admin_state) |
| && (BCMBAL_STATE_DOWN != p_sub_term_inst->current_sub_term_info.data.admin_state)) |
| { |
| p_sub_term_inst->current_sub_term_info.data.admin_state = BCMBAL_STATE_DOWN; |
| |
| /* Set the expected state of the oper_status upon success */ |
| p_sub_term_inst->api_req_sub_term_info.data.oper_status = BCMBAL_STATUS_DOWN; |
| |
| fsm_event.event_type = SUB_TERM_FSM_EVENT_TYPE_ADMIN_DN; |
| b_generate_event = BCMOS_TRUE; |
| } |
| else |
| { |
| /* @todo implement a MODIFY here */ |
| BCM_LOG(INFO, log_id_sub_term, "no state change...done\n"); |
| break; /* no state change detected - do nothing for now */ |
| } |
| |
| /* If there was an event generated, call the state machine exec */ |
| if(BCMOS_TRUE == b_generate_event) |
| { |
| /* |
| * Run the sub_term FSM to process this event |
| */ |
| ret = sub_term_fsm_exec(p_sub_term_inst, &fsm_event); |
| } |
| break; |
| } |
| |
| case (BCMBAL_OBJ_MSG_TYPE_GET): |
| { |
| |
| bcmbal_aggregation_port_id_list_u8 agg_port_id_list = {}; |
| bcmbal_service_port_id_list_u8 svc_port_id_list = {}; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "Processing a sub_term GET REQ mgmt message\n"); |
| |
| /* |
| * Just return the sub_term data info that we have on record for |
| * this sub_term instance |
| */ |
| |
| /* |
| * Find the specified sub_term instance |
| */ |
| p_sub_term_inst = sub_term_inst_get(sub_term_key, SUB_TERM_FLAG_ACTIVE); |
| |
| if(NULL == p_sub_term_inst) |
| { |
| /* This is not a fatal error condition |
| */ |
| BCM_LOG(ERROR, log_id_sub_term, "Specified sub_term not found on GET\n"); |
| ret = BCM_ERR_NOENT; |
| } |
| else |
| { |
| do |
| { |
| /* Return the agg_port_id list if requested */ |
| BCMBAL_CFG_PROP_CLEAR(&p_sub_term_inst->current_sub_term_info, |
| subscriber_terminal, |
| agg_port_id_list); |
| |
| |
| /* If the user requested the list of agg_port_ids for this subscriber terminal |
| * then return the list. |
| */ |
| if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg, |
| subscriber_terminal, |
| agg_port_id_list)) |
| { |
| |
| if(BCM_ERR_OK == agg_port_id_list_fill(p_sub_term_inst, &agg_port_id_list)) |
| { |
| /* NOTE: The returned list may be empty */ |
| BCMBAL_CFG_PROP_SET(&p_sub_term_inst->current_sub_term_info, |
| subscriber_terminal, |
| agg_port_id_list, |
| agg_port_id_list); |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_sub_term, "Error trying to fill agg_port list to return\n"); |
| ret = BCM_ERR_INTERNAL; |
| break; |
| |
| } |
| } |
| |
| /* Return the svc_port_id list if requested */ |
| BCMBAL_CFG_PROP_CLEAR(&p_sub_term_inst->current_sub_term_info, |
| subscriber_terminal, |
| svc_port_id_list); |
| |
| /* If the user requested the list of sub_term_ids for this subscriber terminal, |
| * then return the list. |
| */ |
| if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg, |
| subscriber_terminal, |
| svc_port_id_list)) |
| { |
| |
| if(BCM_ERR_OK == svc_port_id_list_fill(p_sub_term_inst, &svc_port_id_list)) |
| { |
| /* NOTE: The returned list may be empty */ |
| BCMBAL_CFG_PROP_SET(&p_sub_term_inst->current_sub_term_info, |
| subscriber_terminal, |
| svc_port_id_list, |
| svc_port_id_list); |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_sub_term, "Error trying to fill svc_port list to return\n"); |
| ret = BCM_ERR_INTERNAL; |
| 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. |
| */ |
| |
| p_sub_term_inst->current_sub_term_info.hdr.hdr.comm_hdr = ((bcmbal_obj *)msg_payload)->comm_hdr; |
| *((bcmbal_subscriber_terminal_cfg *)msg_payload) = p_sub_term_inst->current_sub_term_info; |
| } |
| |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term); |
| |
| /* Free the temporary lists if they were used */ |
| if(svc_port_id_list.val) |
| { |
| bcmos_free(svc_port_id_list.val); |
| } |
| |
| if(agg_port_id_list.val) |
| { |
| bcmos_free(agg_port_id_list.val); |
| } |
| |
| break; |
| } |
| |
| case (BCMBAL_OBJ_MSG_TYPE_CLEAR): |
| { |
| /* |
| * Find the specified sub_term instance |
| */ |
| p_sub_term_inst = sub_term_inst_get(sub_term_key, SUB_TERM_FLAG_ACTIVE); |
| |
| if(NULL == p_sub_term_inst) |
| { |
| /* This is not a fatal error condition |
| */ |
| BCM_LOG(ERROR, log_id_sub_term, "Specified sub_term not found on CLEAR\n"); |
| ret = BCM_ERR_NOENT; |
| } |
| else |
| { |
| /* |
| * Fill in the local sub_term instance API request data structure |
| */ |
| p_sub_term_inst->api_req_sub_term_info = *p_sub_term_cfg; |
| } |
| |
| /* We respond to the BAL public API backend with a result. |
| */ |
| mgmt_msg_send_balapi_rsp(ret, msg_payload, oper_type, log_id_sub_term); |
| |
| if(BCM_ERR_OK == ret) |
| { |
| fsm_event.event_type = SUB_TERM_FSM_EVENT_TYPE_REMOVE; |
| |
| /* Run the sub_term FSM to process this event */ |
| ret = sub_term_fsm_exec(p_sub_term_inst, &fsm_event); |
| } |
| |
| break; |
| } |
| |
| default: |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Unsupported operation on sub_term 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_sub_term); |
| break; |
| } |
| } |
| |
| return ret; |
| } |
| |
| |
| bcmos_errno process_subscriber_terminal_util_msg(void *msg_payload) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| sub_term_inst *p_sub_term_inst = NULL; |
| bcmbal_msg_type type; |
| sub_term_fsm_event sub_term_event; |
| bcmbal_subscriber_terminal_key key; |
| |
| BUG_ON(NULL == msg_payload); |
| |
| type = bcmbal_type_minor_get(msg_payload); |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "Processing a sub_term %s util message from %s\n", |
| bcmbal_msg_t_str[type], |
| subsystem_str[bcmbal_sender_get(msg_payload)]); |
| |
| /* recover the key from the message */ |
| key = ((bal_util_msg_ind *)msg_payload)->obj_key.sub_term_key; |
| |
| do |
| { |
| BCM_LOG(DEBUG, log_id_sub_term, "Got sub_term key id from util (ID%d, PON %d)\n", |
| key.sub_term_id, key.intf_id); |
| |
| /* Don't bother to look up the sub_term instance for DISCOVERY messages from the |
| * mac util where the sub_term_id is unknown. This is a new ONU, so it will not |
| * be found in the ACTIVE table. |
| */ |
| if((BAL_MSG_TYPE_AUTO_IND != (bcmbal_msg_type)type) || |
| (BAL_MSG_TYPE_AUTO_IND == (bcmbal_msg_type)type && BCMBAL_SUB_ID_UNKNOWN != key.sub_term_id)) |
| { |
| /* |
| * Get the sub_term instance that's being referenced |
| */ |
| p_sub_term_inst = sub_term_inst_get(&key, SUB_TERM_FLAG_ACTIVE); |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "invalid sub_term (ID%d, PON%d) found while processing a util message type %s from %s\n", |
| key.sub_term_id, |
| key.intf_id, |
| bcmbal_msg_t_str[type], |
| subsystem_str[bcmbal_sender_get(msg_payload)]); |
| |
| ret = BCM_ERR_INTERNAL; |
| |
| break; |
| } |
| } |
| |
| /* |
| * Record the msg for further processing access |
| */ |
| sub_term_event.msg = msg_payload; |
| |
| if (BAL_MSG_TYPE_IND == type) |
| { |
| sub_term_event.event_type = SUB_TERM_FSM_EVENT_TYPE_UTIL_MSG; |
| } |
| else if (BAL_MSG_TYPE_AUTO_IND == type) |
| { |
| sub_term_event.event_type = SUB_TERM_FSM_EVENT_TYPE_UTIL_AUTO_MSG; |
| } |
| else |
| { |
| ret = BCM_ERR_NOT_SUPPORTED; |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Unknown message type received from the APP (not one of RSP:ACK:IND:AUTO_IND) (type:%d)\n", |
| type); |
| } |
| |
| if (p_sub_term_inst) |
| { |
| BCM_LOG(DEBUG, log_id_sub_term, "p_sub_term_inst->fsm_state=%d , sub_term_event.event_type = %d\n", |
| p_sub_term_inst->fsm_state, sub_term_event.event_type); |
| } |
| else |
| { |
| if (BAL_MSG_TYPE_IND == type) |
| { |
| BCM_LOG(WARNING, log_id_sub_term, "p_sub_term_inst is NULL\n"); |
| } |
| } |
| /* |
| * Run the Sub_Term FSM to process this event |
| */ |
| if(BCM_ERR_OK == ret) |
| { |
| ret = sub_term_fsm_exec(p_sub_term_inst, &sub_term_event); |
| } |
| } |
| while(0); |
| |
| return ret; |
| } |
| |
| /************************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing for a subscriber-terminal |
| * admin-up command received from the BAL Public API when the specified |
| * subscriber-terminal instance is in the admin-down state (i.e. when |
| * the subscriber-terminal instance FSM is in the NULL or REMOVED state). |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| ***********************************************************************************/ |
| static bcmos_errno sub_term_fsm_admin_up_start(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(INFO, log_id_sub_term, |
| "Received a admin UP request from BAL API - bringing up SUB_TERM\n"); |
| |
| /* change subscriber terminal state to CONFIGURING */ |
| p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURING; |
| |
| /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */ |
| ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_ADD, BCMOS_FALSE); |
| |
| do |
| { |
| |
| /* check for object in wrong state, this is not an actual error */ |
| if(BCM_ERR_STATE == ret) |
| { |
| BCM_LOG(INFO, log_id_sub_term, |
| "mac_util_subscriber_terminal_set() subscriber_terminal could not be activated at this time\n"); |
| |
| } |
| /* check for errors */ |
| else if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Error detected in mac_util_subscriber_terminal_set(): %s\n", |
| bcmos_strerror(ret)); |
| break; |
| |
| } |
| |
| /* The hardware has properly accepted the object info, so the request object becomes |
| * the current state, except for the oper_status. |
| */ |
| bcmbal_sub_term_object_overlay_w_src_priority(&p_sub_term_inst->current_sub_term_info, |
| &p_sub_term_inst->api_req_sub_term_info); |
| |
| /* Add this subscriber_terminal to the list of subscriber_terminals associated with it's interface */ |
| bcmbal_interface_sub_term_list_entry_add(p_sub_term_inst->current_sub_term_info.key); |
| |
| /* Record that this object is in progress */ |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_TRUE); |
| |
| } while(0); |
| |
| /* If there were errors during processing, then report the error to the API */ |
| if(BCM_ERR_OK != ret) |
| { |
| mgmt_msg_send_balapi_ind(ret, |
| msg, |
| log_id_sub_term); |
| } |
| |
| return ret; |
| |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The subscriber terminal FSM state processing for a subscriber terminal |
| * admin-up command received from the BAL Public API when the specified |
| * subscriber terminal FSM is already in the REMOVING state. |
| * |
| * @param p_sub_term_inst Pointer to a subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_admin_up_error(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_STATE; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "Received a admin UP request from BAL API - returning ERROR to the API" |
| " - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing for an subscriber-terminal |
| * admin-down command received from the BAL Public API when the specified |
| * subscriber-terminal is admin-up (i.e when the specified subscriber-terminal |
| * instance FSM is in the CONFIGURED state). |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_admin_dn_start(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(INFO, log_id_sub_term, |
| "Received a admin DOWN request from BAL API - bringing down SUB_TERM\n"); |
| |
| /* change subscriber terminal state to CONFIGURING */ |
| p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURING; |
| |
| /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */ |
| ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_REMOVE, BCMOS_FALSE); |
| |
| /* check for errors */ |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Error detected in mac_util_subscriber_terminal_set(): %s\n", |
| bcmos_strerror(ret)); |
| |
| /* report the status to the API */ |
| mgmt_msg_send_balapi_ind(ret, |
| msg, |
| log_id_sub_term); |
| |
| |
| } |
| else |
| { |
| /* NOTE: The hardware has properly accepted the object info but we do |
| * not overwrite the current subscriber terminal data as there is nothing in the request |
| * that is relevant besides the admin_state. We merely set the object to in_progress. |
| */ |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_TRUE); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing for an subscriber-terminal |
| * clear command received from the BAL Public API |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_removing_start(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(INFO, log_id_sub_term, |
| "Received a REMOVE request from BAL API - removing SUB_TERM\n"); |
| |
| /* change subscriber terminal state to REMOVING */ |
| p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_REMOVING; |
| |
| /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */ |
| ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_CLEAR, BCMOS_FALSE); |
| |
| /* check for errors */ |
| if(BCM_ERR_OK != ret) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Error detected in mac_util_subscriber_terminal_set(): %s\n", |
| bcmos_strerror(ret)); |
| |
| /* report the error to the API */ |
| mgmt_msg_send_balapi_ind(ret, |
| msg, |
| log_id_sub_term); |
| } |
| else |
| { |
| /* The hardware has properly accepted the object info, so the request object becomes |
| * the current state, except for the oper_status. |
| */ |
| bcmbal_sub_term_object_overlay_w_src_priority(&p_sub_term_inst->current_sub_term_info, |
| &p_sub_term_inst->api_req_sub_term_info); |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_TRUE); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing for subscriber-terminal |
| * admin-down command from the BAL Public API when the specified |
| * subscriber-terminal is already admin-down. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_admin_dn_ok(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "Received a admin DOWN request from BAL API - returning OK to the API" |
| " - no further function\n"); |
| |
| mgmt_msg_send_balapi_ind(ret, |
| msg, |
| log_id_sub_term); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The subscriber terminal FSM state processing for a subscriber terminal |
| * admin-down command received from the BAL Public API when the specified |
| * subscriber terminal FSM is already in the REMOVING state. |
| * |
| * @param p_sub_term_inst Pointer to a subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_admin_dn_error(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_STATE; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "Received a admin DOWN request from BAL API - returning ERROR to the API" |
| " - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to ignore a |
| * received message. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from the BAL Public API |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_ignore_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "Ignoring message from BAL utils\n"); |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to process an |
| * AUTO IND message from one of the BAL apps while in the NULL state. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_null_process_util_auto_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| bcmbal_subscriber_terminal_cfg subscriber_terminal_obj; |
| bcmbal_serial_number serial = {}; |
| bal_util_msg_ind *ind_msg; |
| |
| /* Process checks */ |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| ind_msg = (bal_util_msg_ind *)msg; |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "Received a AUTO IND in the null state\n"); |
| |
| /* |
| * Set the key in the subscriber_terminal object |
| */ |
| BCMBAL_CFG_INIT(&subscriber_terminal_obj, subscriber_terminal, ind_msg->obj_key.sub_term_key); |
| |
| /* |
| * Set the serial number in the subscriber_terminal object |
| */ |
| memcpy(&serial, ind_msg->data, sizeof(bcmbal_serial_number)); |
| BCMBAL_CFG_PROP_SET(&subscriber_terminal_obj, subscriber_terminal, serial_number, serial); |
| |
| /* And mark it's status as DOWN */ |
| BCMBAL_CFG_PROP_SET(&subscriber_terminal_obj, subscriber_terminal, oper_status, BCMBAL_STATUS_DOWN); |
| |
| /* |
| * Send the indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| (void *)&subscriber_terminal_obj.hdr, |
| log_id_sub_term); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to process an |
| * AUTO IND message from one of the BAL apps while in the CONFIGURING state. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_configuring_process_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret; |
| bal_util_msg_ind *ind_msg; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_sub_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| 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_sub_term, |
| " Received a IND message from BAL UTIL (%s) during CONFIGURING state\n", |
| subsystem_str[bcmbal_sender_get(msg)]); |
| |
| /* Handle response */ |
| ret = ind_msg->status; |
| |
| if(BCM_ERR_OK == ret) |
| { |
| |
| /* If this indication is for a subscriber terminal that has been ADDED and is ADMIN_UP, |
| * OR for a subscriber terminal that has been REMOVED and is ADMIN_DOWN |
| * then complete the state transition. |
| */ |
| |
| if((BAL_UTIL_OPER_SUB_TERM_ADD == bcmbal_msg_id_oper_get(msg) && |
| BCMBAL_STATE_UP == p_sub_term_inst->current_sub_term_info.data.admin_state) || |
| (BAL_UTIL_OPER_SUB_TERM_REMOVE == bcmbal_msg_id_oper_get(msg) && |
| BCMBAL_STATE_DOWN == p_sub_term_inst->current_sub_term_info.data.admin_state)) |
| { |
| |
| if (bcm_topo_pon_get_pon_family(p_sub_term_inst->current_sub_term_info.key.intf_id) == BCM_TOPO_PON_FAMILY_EPON) |
| { |
| uint16_t tunnel_id; |
| |
| /* Recover the tunnel_id from the indication message */ |
| memcpy(&tunnel_id, ind_msg->data, sizeof(tunnel_id)); |
| |
| /* And store it in the sub_term instance, to be used by the switch */ |
| p_sub_term_inst->current_sub_term_info.data.svc_port_id = tunnel_id; |
| } |
| |
| p_sub_term_inst->current_sub_term_info.data.oper_status = |
| p_sub_term_inst->api_req_sub_term_info.data.oper_status; |
| |
| /* |
| * The subscriber terminal has been successfully configured |
| */ |
| p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURED; |
| |
| } |
| |
| } |
| else |
| { |
| /* Error */ |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Failed in state %s;%s\n", |
| sub_term_state_name_get(p_sub_term_inst->fsm_state), |
| bcmos_strerror(ret)); |
| } |
| |
| BCMBAL_OBJ_IN_PROGRESS_SET(&(p_sub_term_inst->current_sub_term_info), BCMOS_FALSE); |
| |
| /* |
| * Send the indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| (void *)&p_sub_term_inst->current_sub_term_info.hdr, |
| log_id_sub_term); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to process an |
| * IND message from one of the BAL apps while in the CONFIGURED state. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_configured_process_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| /* Process checks */ |
| BUG_ON(NULL == p_sub_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| " Received a IND message from BAL UTIL (%s) during CONFIGURED state\n", |
| subsystem_str[bcmbal_sender_get(msg)]); |
| |
| if((BAL_UTIL_OPER_SUB_TERM_REMOVE != bcmbal_msg_id_oper_get(msg)) && |
| (BAL_UTIL_OPER_SUB_TERM_CLEAR != bcmbal_msg_id_oper_get(msg))) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Received an unrecognized IND (%u) received in the configured state" |
| "- no further function\n", bcmbal_msg_id_oper_get(msg)); |
| } |
| else |
| { |
| |
| |
| /* change subscriber terminal state to CONFIGURING */ |
| p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURING; |
| |
| /* Set the oper_status upon success */ |
| p_sub_term_inst->current_sub_term_info.data.oper_status = BCMBAL_STATUS_NOT_PRESENT; |
| |
| /* |
| * Send the indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| &p_sub_term_inst->current_sub_term_info.hdr, |
| log_id_sub_term); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to process an |
| * AUTO IND message from one of the BAL apps while in the CONFIGURED state. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_configuring_process_util_auto_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| /* Process checks */ |
| BUG_ON(NULL == p_sub_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| " Received a AUTO IND message from BAL UTIL (%s) during CONFIGURING state\n", |
| subsystem_str[bcmbal_sender_get(msg)]); |
| |
| if(BAL_UTIL_OPER_SUB_TERM_DISCOVERY != bcmbal_msg_id_oper_get(msg)) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Received an unrecognized AUTO IND in the configuring state" |
| "- no further function\n"); |
| } |
| else |
| { |
| /*– Core calls Mac Utils to set the subscriber-terminal parameters using the applicable SDK calls */ |
| /* send TRUE in last argument to indicate the request is after a ONU Discovery */ |
| ret = mac_util_subscriber_terminal_set(p_sub_term_inst, BAL_UTIL_OPER_SUB_TERM_ADD, BCMOS_TRUE); |
| } |
| |
| /* If there were errors during processing, then report the error to the API */ |
| if(BCM_ERR_OK != ret) |
| { |
| |
| mgmt_msg_send_balapi_ind(ret, |
| (void *)&p_sub_term_inst->current_sub_term_info.hdr, |
| log_id_sub_term); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to process a |
| * message from one of the BAL apps while in the REMOVING state. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_removing_process_util_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret; |
| bal_util_msg_ind *ind_msg; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_sub_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| 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. |
| */ |
| |
| /* Handle indication */ |
| ret = ind_msg->status; |
| |
| BCM_LOG(INFO, log_id_sub_term, |
| "Received a %s message from BAL APP (%s) during REMOVING state\n", |
| (BAL_MSG_TYPE_IND == bcmbal_type_minor_get(msg)) ? "IND" : "RSP", |
| subsystem_str[bcmbal_sender_get(msg)]); |
| |
| if(BCM_ERR_OK == ret) |
| { |
| /* Set the admin_state and oper_status to be DOWN and NOT_PRESENT respectively, |
| * since we are clearing this object anyway. These parameters are set in the free function, |
| * but they need to be set here for the indication below to be correct */ |
| p_sub_term_inst->current_sub_term_info.data.admin_state = BCMBAL_STATE_DOWN; |
| p_sub_term_inst->current_sub_term_info.data.oper_status = BCMBAL_STATUS_NOT_PRESENT; |
| } |
| |
| if(BCM_ERR_OK == ret) |
| { |
| |
| /* Remove this subscriber_terminal from the list of subscriber_terminals associated with it's interface */ |
| bcmbal_interface_sub_term_list_entry_remove(p_sub_term_inst->current_sub_term_info.key); |
| |
| /* |
| * Send the success indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| &p_sub_term_inst->current_sub_term_info.hdr, |
| log_id_sub_term); |
| |
| /* Return the subscriber terminal to the free pool */ |
| sub_term_free_by_entry(p_sub_term_inst); |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "sub term freed\n"); |
| |
| } |
| else |
| { |
| p_sub_term_inst->fsm_state = SUB_TERM_FSM_STATE_CONFIGURED; |
| |
| /* |
| * Send the failure indication back to the BAL public API here |
| */ |
| mgmt_msg_send_balapi_ind(ret, |
| &p_sub_term_inst->current_sub_term_info.hdr, |
| log_id_sub_term); |
| |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Error encountered in REMOVING state (status is %s)\n", |
| bcmos_strerror(ret)); |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM state processing function to process an |
| * AUTO IND message from one of the BAL apps while in the REMOVING state. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps. |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_removing_process_util_auto_msg(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| /* Parameter checks */ |
| BUG_ON(NULL == p_sub_term_inst); |
| BUG_ON(NULL == msg); |
| BUG_ON(NULL == p_event); |
| |
| BCM_LOG(DEBUG, log_id_sub_term, |
| "Received a AUTO IND in the removing state" |
| " - no further function\n"); |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief The Subscriber terminal FSM function which is executed when an error |
| * is encountered during FSM processing. |
| * |
| * @param p_sub_term_inst Pointer to an subscriber terminal instance |
| * @param msg Pointer to a BAL message received from one of |
| * the BAL apps |
| * @param p_event Pointer to an subscriber terminal event structure |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_fsm_state_err(sub_term_inst *p_sub_term_inst, |
| void *msg, |
| sub_term_fsm_event *p_event) |
| { |
| bcmos_errno ret = BCM_ERR_INVALID_OP; |
| |
| BCM_LOG(ERROR, log_id_sub_term, |
| "Error encountered processing SUB_TERM FSM - BAD EVENT ()\n"); |
| |
| return ret; |
| } |
| |
| |
| /* |
| * Helper functions |
| */ |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to retrieve a subscriber-terminal instance of the specified |
| * class. |
| * |
| * @param key A pointer to the key of the subscriber-terminal being |
| * referenced |
| * @param search_flag A flag specifying the type of subscriber-terminal |
| * instance to be retrieved |
| * |
| * @returns sub_term_inst_t* A pointer to the found subscriber-terminal instance, |
| * or NULL if one is not found |
| *****************************************************************************/ |
| sub_term_inst *sub_term_inst_get(bcmbal_subscriber_terminal_key *key, |
| sub_term_flag search_flag) |
| { |
| sub_term_inst *current_entry = NULL; |
| sub_term_inst *p_temp_entry; |
| |
| /* |
| * First, check the active list |
| */ |
| TAILQ_FOREACH(current_entry, |
| &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list, |
| sub_term_inst_next) |
| { |
| if((current_entry->api_req_sub_term_info.key.sub_term_id == key->sub_term_id) && |
| (current_entry->api_req_sub_term_info.key.intf_id == key->intf_id)) |
| { |
| /* The sub_term instance pointer is in current_entry */ |
| break; |
| } |
| } |
| |
| |
| if((SUB_TERM_FLAG_ANY == search_flag) && (NULL == current_entry)) |
| { |
| /* Now check the free list */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list, |
| sub_term_inst_next, |
| p_temp_entry) |
| { |
| /* Remove it from the free list */ |
| TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list, |
| current_entry, sub_term_inst_next); |
| |
| /* And add it to the active list */ |
| TAILQ_INSERT_TAIL(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list, |
| current_entry, sub_term_inst_next); |
| |
| /* |
| * Initialize the sub_term data |
| */ |
| current_entry->fsm_state = SUB_TERM_FSM_STATE_NULL; |
| |
| break; |
| } |
| } |
| |
| if(NULL == current_entry) |
| { |
| /* |
| * A sub_term was not found on either list*/ |
| |
| BCM_LOG(DEBUG, log_id_sub_term, "no sub_term found\n"); |
| } |
| |
| return current_entry; |
| } |
| |
| bcmos_errno sub_term_svc_port_id_get(bcmbal_sub_id sub_term_id, |
| uint16_t access_int_id, |
| bcmbal_service_port_id *p_svc_port_id) |
| { |
| sub_term_inst *p_sub_term_inst; |
| bcmbal_subscriber_terminal_key sub_term_key; |
| bcmos_errno ret = BCM_ERR_OK; |
| |
| BUG_ON(NULL == p_svc_port_id); |
| |
| /* Create the key to find the subscriber terminal instance being referenced */ |
| sub_term_key.sub_term_id = sub_term_id; |
| sub_term_key.intf_id = access_int_id; |
| |
| if(NULL == (p_sub_term_inst = sub_term_inst_get(&sub_term_key, SUB_TERM_FLAG_ACTIVE))) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, "Specified sub_term (sub:%d on int:%d) not found\n", |
| sub_term_id, access_int_id); |
| ret = BCM_ERR_NOENT; |
| } |
| else |
| { |
| *p_svc_port_id = p_sub_term_inst->current_sub_term_info.data.svc_port_id; |
| } |
| |
| return ret; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief A function to free a subscriber terminal instance specified |
| * by a the supplied entry pointer. |
| * |
| * @param p_entry A pointer to the entry to be freed |
| * |
| * |
| * @returns bcmos_errno |
| *****************************************************************************/ |
| static bcmos_errno sub_term_free_by_entry(sub_term_inst *p_entry) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| sub_term_inst *current_entry; |
| sub_term_inst *p_temp_entry; |
| |
| BUG_ON(NULL == p_entry); |
| |
| /* |
| * First, check the active list (an active sub_term can be in the adding or removing state) |
| */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list, |
| sub_term_inst_next, |
| p_temp_entry) |
| { |
| if(current_entry == p_entry) |
| { |
| /* Remove it from the active list */ |
| TAILQ_REMOVE(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->active_sub_term_list, |
| current_entry, sub_term_inst_next); |
| } |
| } |
| |
| /* Initialize the svc_port_id and agg_port_id lists */ |
| p_entry->num_svc_port_ids = 0; |
| TAILQ_INIT(&p_entry->svc_port_id_list); |
| |
| p_entry->num_agg_port_ids = 0; |
| TAILQ_INIT(&p_entry->agg_port_id_list); |
| |
| /* And add the entry to the free list */ |
| p_entry->fsm_state = SUB_TERM_FSM_STATE_NULL; |
| |
| /* And initialize the current object in the sub_term instance */ |
| sub_term_inst_entry_obj_init(p_entry); |
| |
| TAILQ_INSERT_TAIL(&SUB_TERM_FSM_SUB_TERM_LIST_CTX_PTR->free_sub_term_list, |
| p_entry, sub_term_inst_next); |
| |
| return ret; |
| } |
| |
| bcmos_errno bcmbal_sub_term_svc_port_id_list_entry_add(sub_term_inst *p_sub_term_inst, |
| bcmbal_service_port_id svc_port_id) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| svc_port_id_entry *current_entry; |
| |
| do |
| { |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "attempting to add a svc_port_id (%u) entry " |
| "to NULL subscriber terminal\n", |
| svc_port_id); |
| |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| /* Check if the id is already on the list before adding it */ |
| TAILQ_FOREACH(current_entry, |
| &p_sub_term_inst->svc_port_id_list, |
| next) |
| { |
| if(current_entry->svc_port_id == svc_port_id) |
| { |
| ret = BCM_ERR_ALREADY; |
| break; |
| } |
| } |
| |
| if(BCM_ERR_OK == ret) |
| { |
| /* Get a new entry and configure it */ |
| current_entry = bcmos_calloc(sizeof(svc_port_id_entry)); |
| |
| if (NULL == current_entry) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "No memory available\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| current_entry->svc_port_id = svc_port_id; |
| |
| /* Save the entry on the list of subscriber-terminal ids on this interface */ |
| TAILQ_INSERT_TAIL(&p_sub_term_inst->svc_port_id_list, |
| current_entry, next); |
| |
| (p_sub_term_inst->num_svc_port_ids)++; |
| } |
| |
| current_entry->ref_count++; |
| |
| } while (0); |
| |
| return ret; |
| |
| } |
| |
| bcmos_errno bcmbal_sub_term_svc_port_id_list_entry_remove(sub_term_inst *p_sub_term_inst, |
| bcmbal_service_port_id svc_port_id) |
| { |
| bcmos_errno ret = BCM_ERR_NOENT; |
| svc_port_id_entry *current_entry, *p_temp_entry; |
| |
| do |
| { |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "attempting to remove a svc_port_id (%u) entry " |
| "from a NULL subscriber terminal\n", |
| svc_port_id); |
| |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| /* Check if the id is on the list */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &p_sub_term_inst->svc_port_id_list, |
| next, |
| p_temp_entry) |
| { |
| if(current_entry->svc_port_id == svc_port_id) |
| { |
| if(0 == --current_entry->ref_count) |
| { |
| /* Remove it from the list of agg_port_ids on this subscriber terminal */ |
| TAILQ_REMOVE(&p_sub_term_inst->svc_port_id_list, |
| current_entry, next); |
| |
| bcmos_free(current_entry); |
| |
| (p_sub_term_inst->num_svc_port_ids)--; |
| } |
| |
| ret = BCM_ERR_OK; |
| break; |
| } |
| } |
| } while (0); |
| |
| return ret; |
| } |
| |
| bcmos_errno bcmbal_sub_term_agg_port_id_list_entry_add( sub_term_inst *p_sub_term_inst, |
| bcmbal_aggregation_port_id agg_port_id) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| agg_port_id_entry *current_entry; |
| |
| do |
| { |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "attempting to add a svc_port_id (%u) entry " |
| "to a NULL subscriber terminal\n", |
| agg_port_id); |
| |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| /* Check if the id is already on the list before adding it */ |
| TAILQ_FOREACH(current_entry, |
| &p_sub_term_inst->agg_port_id_list, |
| next) |
| { |
| if(current_entry->agg_port_id == agg_port_id) |
| { |
| ret = BCM_ERR_ALREADY; |
| break; |
| } |
| } |
| |
| if(BCM_ERR_OK == ret) |
| { |
| /* Get a new entry and configure it */ |
| current_entry = bcmos_calloc(sizeof(agg_port_id_entry)); |
| |
| if (NULL == current_entry) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "No memory available\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| current_entry->agg_port_id = agg_port_id; |
| |
| /* Save the entry on the list of subscriber-terminal ids on this interface */ |
| TAILQ_INSERT_TAIL(&p_sub_term_inst->agg_port_id_list, |
| current_entry, next); |
| |
| (p_sub_term_inst->num_agg_port_ids)++; |
| } |
| |
| (current_entry->ref_count)++; |
| |
| } while (0); |
| |
| return ret; |
| |
| } |
| |
| bcmos_errno bcmbal_sub_term_agg_port_id_list_entry_remove(sub_term_inst *p_sub_term_inst, |
| bcmbal_aggregation_port_id agg_port_id) |
| { |
| bcmos_errno ret = BCM_ERR_NOENT; |
| agg_port_id_entry *current_entry, *p_temp_entry; |
| |
| do |
| { |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "attempting to remove a agg_port_id (%u) entry " |
| "from a NULL subscriber terminal\n", |
| agg_port_id); |
| |
| ret = BCM_ERR_NOENT; |
| break; |
| } |
| |
| /* Check if the id is on the list */ |
| TAILQ_FOREACH_SAFE(current_entry, |
| &p_sub_term_inst->agg_port_id_list, |
| next, |
| p_temp_entry) |
| { |
| if(current_entry->agg_port_id == agg_port_id) |
| { |
| if(0 == --current_entry->ref_count) |
| { |
| /* Remove it from the list of agg_port_ids on this subscriber terminal */ |
| TAILQ_REMOVE(&p_sub_term_inst->agg_port_id_list, |
| current_entry, next); |
| |
| bcmos_free(current_entry); |
| |
| (p_sub_term_inst->num_agg_port_ids)--; |
| } |
| |
| ret = BCM_ERR_OK; |
| break; |
| } |
| } |
| } while (0); |
| |
| return ret; |
| } |
| |
| static bcmos_errno svc_port_id_list_fill(sub_term_inst *p_sub_term_inst, |
| bcmbal_service_port_id_list_u8 *svc_port_id_list) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| svc_port_id_entry *current_entry = NULL; |
| int ii = 0; |
| |
| do |
| { |
| /* Traverse the list of svc_port_ids recorded and fill in the list to be returned */ |
| svc_port_id_list->len = p_sub_term_inst->num_svc_port_ids; |
| svc_port_id_list->val = bcmos_calloc(sizeof(bcmbal_service_port_id) * svc_port_id_list->len); |
| |
| if (NULL == svc_port_id_list->val) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "No memory available\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| TAILQ_FOREACH(current_entry, |
| &p_sub_term_inst->svc_port_id_list, |
| next) |
| { |
| svc_port_id_list->val[ii++] = current_entry->svc_port_id; |
| } |
| |
| } while (0); |
| |
| return ret; |
| } |
| |
| static bcmos_errno agg_port_id_list_fill(sub_term_inst *p_sub_term_inst, |
| bcmbal_aggregation_port_id_list_u8 *agg_port_id_list) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| agg_port_id_entry *current_entry = NULL; |
| int ii = 0; |
| |
| do |
| { |
| /* Traverse the list of svc_port_ids recorded and fill in the list to be returned */ |
| agg_port_id_list->len = p_sub_term_inst->num_agg_port_ids; |
| agg_port_id_list->val = bcmos_calloc(sizeof(bcmbal_aggregation_port_id) * agg_port_id_list->len); |
| |
| if (NULL == agg_port_id_list->val) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "No memory available\n"); |
| ret = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| TAILQ_FOREACH(current_entry, |
| &p_sub_term_inst->agg_port_id_list, |
| next) |
| { |
| agg_port_id_list->val[ii++] = current_entry->agg_port_id; |
| } |
| |
| } while (0); |
| |
| return ret; |
| } |
| |
| bcmos_errno bcmbal_sub_term_check_svc_port_in_use(sub_term_inst *p_sub_term_inst, |
| bcmbal_service_port_id svc_port_id) |
| { |
| bcmos_errno ret = BCM_ERR_NOENT; |
| svc_port_id_entry *current_entry = NULL; |
| |
| do |
| { |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "NULL subscriber terminal\n"); |
| |
| break; |
| } |
| |
| /* Check if the id is on the list */ |
| TAILQ_FOREACH(current_entry, |
| &p_sub_term_inst->svc_port_id_list, |
| next) |
| { |
| if(current_entry->svc_port_id == svc_port_id) |
| { |
| ret = BCM_ERR_OK; |
| break; |
| } |
| } |
| } while (0); |
| |
| return ret; |
| } |
| |
| bcmos_errno bcmbal_sub_term_check_agg_port_in_use(sub_term_inst *p_sub_term_inst, |
| bcmbal_aggregation_port_id agg_port_id) |
| { |
| bcmos_errno ret = BCM_ERR_NOENT; |
| agg_port_id_entry *current_entry = NULL; |
| |
| do |
| { |
| if(NULL == p_sub_term_inst) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "NULL subscriber terminal\n"); |
| |
| break; |
| } |
| |
| /* Check if the id is on the list */ |
| TAILQ_FOREACH(current_entry, |
| &p_sub_term_inst->agg_port_id_list, |
| next) |
| { |
| if(current_entry->agg_port_id == agg_port_id) |
| { |
| ret = BCM_ERR_OK; |
| break; |
| } |
| } |
| } while (0); |
| |
| return ret; |
| } |
| |
| |
| |
| static bcmos_errno bcmbal_sub_term_tm_scheds_set(const bcmbal_subscriber_terminal_cfg *p_sub_term_cfg) |
| { |
| bcmos_errno ret = BCM_ERR_OK; |
| bcmbal_tm_sched_key tm_sched_key; |
| |
| do |
| { |
| if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg, subscriber_terminal, us_tm)) |
| { |
| tm_sched_key.dir = BCMBAL_TM_SCHED_DIR_US; |
| tm_sched_key.id = p_sub_term_cfg->data.us_tm; |
| if(BCM_ERR_OK!= (ret = bcmbal_tm_sched_set_sub_term_owner(tm_sched_key, p_sub_term_cfg))) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "failed to set sub term us_tm, ret = %s", bcmos_strerror(ret)); |
| break; |
| } |
| } |
| if(BCMBAL_CFG_PROP_IS_SET(p_sub_term_cfg, subscriber_terminal, ds_tm)) |
| { |
| tm_sched_key.dir = BCMBAL_TM_SCHED_DIR_DS; |
| tm_sched_key.id = p_sub_term_cfg->data.ds_tm; |
| |
| if(BCM_ERR_OK!= (ret = bcmbal_tm_sched_set_sub_term_owner(tm_sched_key, p_sub_term_cfg))) |
| { |
| BCM_LOG(ERROR, log_id_sub_term, |
| "failed to set sub term ds_tm, ret = %s", bcmos_strerror(ret)); |
| break; |
| } |
| } |
| }while(0); |
| return ret; |
| } |
| |
| /*@}*/ |