blob: b08efd6947525a6b2e8b780dd82da53a4f53d00c [file] [log] [blame]
/******************************************************************************
*
* <:copyright-BRCM:2016:DUAL/GPL:standard
*
* Copyright (c) 2016 Broadcom
* All Rights Reserved
*
* Unless you and Broadcom execute a separate written software license
* agreement governing use of this software, this software is licensed
* to you under the terms of the GNU General Public License version 2
* (the "GPL"), available at http://www.broadcom.com/licenses/GPLv2.php,
* with the following added to such license:
*
* As a special exception, the copyright holders of this software give
* you permission to link this software with independent modules, and
* to copy and distribute the resulting executable under terms of your
* choice, provided that you also meet, for each linked independent
* module, the terms and conditions of the license of that module.
* An independent module is a module which is not derived from this
* software. The special exception does not apply to any modifications
* of the software.
*
* Not withstanding the above, under no circumstances may you combine
* this software in any way with any other Broadcom software provided
* under a license other than the GPL, without Broadcom's express prior
* written consent.
*
* :>
*
*****************************************************************************/
/**
* @file bal_mac_util_gpon.c
*
* @brief mac util interfaces definition used by Bal Core, for GPON
*
* This file expose the APIs to the core to configure the mac
* with regarding to the operation of access terminal, interface, subscriber terminal and flow.
*
* @addtogroup mac_util
*/
/*@{*/
#include <bal_mac_util.h>
#include <bal_mac_util_common_itu_pon.h>
static bcmos_errno mac_util_indication_handle_for_gpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg);
static bcmos_errno mac_util_indication_handle_for_gpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg);
static bcmos_errno mac_util_indication_handle_for_gpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg);
static bcmos_errno mac_util_indication_handle_for_gpon_gem_port (bcmolt_devid device_id, bcmolt_msg *p_msg);
/** @brief array stores the list of GPON related auto indications from Maple to subscribe */
static mac_util_ind_obj_and_handlers mac_util_gpon_ind_handlers[] =
{
{BCMOLT_OBJ_ID_GPON_NI, "BCMOLT_OBJ_ID_GPON_NI", mac_util_indication_handle_for_gpon_ni},
{BCMOLT_OBJ_ID_GPON_ONU, "BCMOLT_OBJ_ID_GPON_ONU", mac_util_indication_handle_for_gpon_onu},
{BCMOLT_OBJ_ID_GPON_ALLOC, "BCMOLT_OBJ_ID_GPON_ALLOC", mac_util_indication_handle_for_gpon_alloc_id},
{BCMOLT_OBJ_ID_GPON_GEM_PORT, "BCMOLT_OBJ_ID_GPON_GEM_PORT", mac_util_indication_handle_for_gpon_gem_port}
};
/**
* @brief Map bal GPON transceiver type to bcm68620 transceiver type
*/
static bcmolt_trx_type mac_gpon_bal_trx_type2bcm68620_trx_type(bcmbal_trx_type bal_trx_type, bcmbal_intf_id intf_id)
{
bcmolt_trx_type trx_type = BCMOLT_TRX_TYPE__NUM_OF;
switch (bal_trx_type)
{
case BCMBAL_TRX_TYPE_GPON_SPS_43_48:
trx_type = BCMOLT_TRX_TYPE_SPS_43_48_H_HP_CDE_SD_2013;
break;
case BCMBAL_TRX_TYPE_GPON_SPS_SOG_4321:
trx_type = BCMOLT_TRX_TYPE_SOG_4321_PSGB;
break;
case BCMBAL_TRX_TYPE_GPON_LTE_3680_M:
trx_type = BCMOLT_TRX_TYPE_LTE_3680_M;
break;
case BCMBAL_TRX_TYPE_GPON_SOURCE_PHOTONICS:
trx_type = BCMOLT_TRX_TYPE_SOURCE_PHOTONICS;
break;
case BCMBAL_TRX_TYPE_GPON_LTE_3680_P:
trx_type = BCMOLT_TRX_TYPE_LTE_3680_P_TYPE_C_PLUS;
break;
default:
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_id), "Invalid trx_type %d\n", bal_trx_type);
}
return trx_type;
}
/**
* @brief all the maple indication handlers for gpon
*
* @param device_id the maple device id generating the current indication
* @param p_msg pointer to the maple indication message
*
*/
bcmos_errno mac_util_handle_all_olt_ind_for_gpon (bcmolt_devid device_id, bcmolt_msg *p_msg)
{
BCM_LOG(DEBUG, log_id_mac_util,
"mac_util_indication_cb received indication obj=%d/%s group=%d subgroup=%d\n",
p_msg->obj_type, mac_util_indication_get_obj_type_str(p_msg->obj_type, mac_util_gpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_gpon_ind_handlers)),
p_msg->group, p_msg->subgroup);
return mac_util_handle_indication(device_id, p_msg, mac_util_gpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_gpon_ind_handlers));
}
/**
* @brief Handler function for Maple auto indications for GPON NI
*
* @param device_id the maple device id generating the current indication
* @param p_msg pointer to the maple indication message
*
* @return bcmos_errno
*/
static bcmos_errno mac_util_indication_handle_for_gpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg)
{
bcmos_errno rc = BCM_ERR_OK;
uint32_t logical_pon;
do
{
/* PON activation */
if (BCMOLT_GPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup)
{
bcmolt_gpon_ni_state_change_completed * p_ind = (bcmolt_gpon_ni_state_change_completed*)p_msg;
rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), "Pon if %d is %s.\n", logical_pon,
BCMOLT_PON_STATE_ACTIVE_WORKING == p_ind->data.new_state ? "up" : "down");
/* if we got something from MAC HW, then it has to be PON interface */
mac_util_report_if_event(logical_pon, BCMBAL_INTF_TYPE_PON, p_msg->err,
p_ind->data.result, p_ind->data.new_state);
}
else if(BCMOLT_GPON_NI_AUTO_CFG_ID_ONU_DISCOVERED == p_msg->subgroup)
{
bcmolt_gpon_ni_onu_discovered *p_ind =
(bcmolt_gpon_ni_onu_discovered *)p_msg;
rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Pon if %d (ONUID:%d) found ONU serial number "
"%c%c%c%c%d%d%d%d%d%d%d%d\n",
logical_pon,
p_ind->data.onu_id,
p_ind->data.serial_number.vendor_id[0],
p_ind->data.serial_number.vendor_id[1],
p_ind->data.serial_number.vendor_id[2],
p_ind->data.serial_number.vendor_id[3],
p_ind->data.serial_number.vendor_specific[0]>>4 & 0x0f,
p_ind->data.serial_number.vendor_specific[0] & 0x0f,
p_ind->data.serial_number.vendor_specific[1]>>4 & 0x0f,
p_ind->data.serial_number.vendor_specific[1] & 0x0f,
p_ind->data.serial_number.vendor_specific[2]>>4 & 0x0f,
p_ind->data.serial_number.vendor_specific[2] & 0x0f,
p_ind->data.serial_number.vendor_specific[3]>>4 & 0x0f,
p_ind->data.serial_number.vendor_specific[3] & 0x0f
);
bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
mac_util_report_sub_term_event(logical_pon,
p_ind->data.onu_id,
&p_ind->data.serial_number,
BAL_UTIL_OPER_SUB_TERM_DISCOVERY,
p_msg->err, BCMOLT_RESULT_SUCCESS,
BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
}
else
{
/* just get the pon key by typecasting to a dummy structure */
bcmolt_gpon_ni_key *p_pon_key = &(((bcmolt_gpon_ni_state_change_completed*)p_msg)->key);
rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Unhandled message indication for obj Gpon_NI group %d "
"subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
}
}
while(0);
return rc;
}
/**
* @brief Handler function for Maple auto indications for GPON ONU
*
* @param device_id the maple device id generating the current indication
* @param p_msg pointer to the maple indication message
*
* @return bcmos_errno
*/
static bcmos_errno mac_util_indication_handle_for_gpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg)
{
bcmos_errno rc = BCM_ERR_OK;
uint32_t logical_pon;
/* just get the pon key by typecasting to a dummy structure */
bcmolt_gpon_onu_key *p_gpon_onu_key = &(((bcmolt_gpon_onu_onu_activation_completed*)p_msg)->key);
do
{
if (BCMOLT_GPON_ONU_AUTO_CFG_ID_ONU_ACTIVATION_COMPLETED == p_msg->subgroup)
{
bcmolt_gpon_onu_onu_activation_completed *p_ind = (bcmolt_gpon_onu_onu_activation_completed*) p_msg;
rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_ind->key.pon_ni),
"sub_term %d (PON%d) activation indication (%s)\n",
p_ind->key.onu_id,
p_ind->key.pon_ni,
bcmos_strerror(p_msg->err));
mac_util_report_sub_term_event(logical_pon,
p_ind->key.onu_id,
(bcmolt_serial_number *)NULL,
BAL_UTIL_OPER_SUB_TERM_ADD,
p_msg->err, p_ind->data.status,
p_ind->data.fail_reason, BCMBAL_INVALID_TUNNEL_ID);
}
else if(BCMOLT_GPON_ONU_AUTO_CFG_ID_ONU_DEACTIVATION_COMPLETED == p_msg->subgroup)
{
bcmolt_gpon_onu_onu_deactivation_completed *p_ind = (bcmolt_gpon_onu_onu_deactivation_completed*) p_msg;
rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"sub_term %d (PON%d) deactivation indication (%s)\n",
p_ind->key.onu_id,
logical_pon,
bcmos_strerror(p_msg->err));
mac_util_report_sub_term_event(logical_pon,
p_ind->key.onu_id,
(bcmolt_serial_number *)NULL,
BAL_UTIL_OPER_SUB_TERM_REMOVE,
p_msg->err, p_ind->data.status,
MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
}
else
{
rc = bcm_topo_pon_get_physical2logical(device_id, p_gpon_onu_key->pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_gpon_onu_key->pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Unhandled message indication for obj GPON_ONU group %d "
"subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
break;
}
rc = mac_util_update_flows_w_sub_term_update(logical_pon, p_gpon_onu_key->onu_id, maple_gpon_mac_check_gem_port_id, maple_gpon_mac_get_alloc_id_config);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to update related flows pon_id = %d onu_id = %d (%s)\n", logical_pon, p_gpon_onu_key->onu_id, bcmos_strerror(rc));
break;
}
}
while(0);
return rc;
}
/**
* @brief Handler function for Maple auto indications for GPON Alloc Id
*
* @param device_id the maple device id generating the current indication
* @param p_msg pointer to the maple indication message
*
* @return bcmos_errno
*/
static bcmos_errno mac_util_indication_handle_for_gpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg)
{
bcmos_errno rc = BCM_ERR_OK;
uint32_t logical_pon;
tm_sched_inst* p_tm_sched_inst = NULL;
do
{
if (BCMOLT_GPON_ALLOC_AUTO_CFG_ID_CONFIGURATION_COMPLETED == p_msg->subgroup)
{
bcmolt_gpon_alloc_configuration_completed *p_ind = (bcmolt_gpon_alloc_configuration_completed*) p_msg;
rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
break;
}
/* Find tn_mode inst owned by that alloc_id and ni */
p_tm_sched_inst = tm_sched_find_agg_port_node(logical_pon, p_ind->key.alloc_id);
if (NULL == p_tm_sched_inst )
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to find tm sched owned by that agg port (intf %d id %d)\n", logical_pon,p_ind->key.alloc_id);
rc = BCM_ERR_NOENT;
break;
}
/*the tm owned by that alloc found, update it with the ind*/
mac_util_report_tm_sched_set_indication(p_tm_sched_inst->req_tm_sched_info.key ,p_msg->err, p_ind->data.status);
}
else
{
/* just get the pon key by typecasting to a dummy structure */
bcmolt_gpon_alloc_key *p_pon_key = &(((bcmolt_gpon_alloc_configuration_completed*)p_msg)->key);
rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Unhandled message indication for obj GPON_ALLOC group %d "
"subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
}
}while (0);
return rc;
}
/**
* @brief Handler function for Maple auto indications for GPON GEM Port
*
* @param device_id the maple device id generating the current indication
* @param p_msg pointer to the maple indication message
*
* @return bcmos_errno
*/
static bcmos_errno mac_util_indication_handle_for_gpon_gem_port (bcmolt_devid device_id, bcmolt_msg *p_msg)
{
bcmos_errno rc = BCM_ERR_OK;
uint32_t logical_pon;
flow_list_entry *p_current_entry = NULL;
void *p_rsc_mgr_curr_entry = NULL;
void *p_rsc_mgr_next_entry = NULL;
do
{
if (BCMOLT_GPON_GEM_PORT_AUTO_CFG_ID_CONFIGURATION_COMPLETED == p_msg->subgroup)
{
bcmolt_gpon_gem_port_configuration_completed *p_ind =
(bcmolt_gpon_gem_port_configuration_completed *) p_msg;
rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_ind->key.pon_ni, bcmos_strerror(rc));
break;
}
/* Find all entries in flows list matching the gem port id and pon ni */
/* use safe walk here because an entry can be removed from list during the walk */
/* get first */
p_current_entry = _mac_util_db_flow_get_next_w_gem (logical_pon, p_ind->key.gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
while (NULL != p_current_entry)
{
/** @note For now this assumes that there is only one op type (add or remove) ,
* that all the flows in an onu are waiting for. We can not have flows waiting on same
* gem for multiple op types, because Maple does not allow multiple configs with
* different op types at the same time.
*/
/* update gem port complete configuration indication received */
p_current_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
/* check if should send flow configuration indication complete to bal core */
rc = check_send_flow_bal_ind_msg(p_current_entry, p_msg->err, p_ind->data.status);
/* any DB cleanup for error should be triggered by Core fsm
* (mac util should not cleanup on its own)
* */
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Failed to send flow configured ind: Error %s, gem port id = %d, pon ni = %d\n",
bcmos_strerror(rc), p_ind->key.gem_port_id, logical_pon);
/* don't break, but continue to check if more flows use the same gem port id */
}
/* get next */
p_current_entry = _mac_util_db_flow_get_next_w_gem (logical_pon, p_ind->key.gem_port_id, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry);
}
}
else
{
/* just get the pon key by typecasting to a dummy structure */
bcmolt_gpon_gem_port_key *p_pon_key = &(((bcmolt_gpon_gem_port_configuration_completed*)p_msg)->key);
rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->pon_ni, &logical_pon);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"Failed to get logical if from physical if (device_id %d physical %d ) (%s)\n", device_id, p_pon_key->pon_ni, bcmos_strerror(rc));
break;
}
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Unhandled message indication for obj GPON_GEM_PORT group %d "
"subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
}
}
while(0);
return rc;
}
/**
* @brief Maple auto indication register for specific GPON based indications
*
* @param p_rx_cfg handler config structure
* @param device_id specific device id (for multiple devices support)
*
* @return bcmos_errno
*/
bcmos_errno mac_util_register_for_gpon_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, bcmolt_devid device_id)
{
return _mac_util_register_for_auto_indications (p_rx_cfg, mac_util_gpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_gpon_ind_handlers), device_id);
}
/*****************************************************************************/
/**
* @brief Map iwf_mode to bcmolt_iwf_mode
*
* @param bal_iwf_mode BAL iwfmode
* @return bcm68620 iwf mode
*/
static bcmolt_iwf_mode bal_iwf_mode2iwf_mode(bcmbal_iwf_mode bal_iwf_mode)
{
bcmolt_iwf_mode iwf_mode = BCMOLT_IWF_MODE__NUM_OF;
switch (bal_iwf_mode)
{
case BCMBAL_IWF_MODE_DIRECT_MAPPING:
iwf_mode = BCMOLT_IWF_MODE_DIRECT_MAPPING_MODE;
break;
case BCMBAL_IWF_MODE_PER_FLOW:
iwf_mode = BCMOLT_IWF_MODE_PER_FLOW_MODE;
break;
default:
BCM_LOG(ERROR, log_id_mac_util, "Invalid iwf_mode %d\n", bal_iwf_mode);
}
return iwf_mode;
}
static bcmos_errno mac_util_access_terminal_set_for_gpon (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_system_mode system_mode, bcmolt_devid device_id)
{
bcmolt_device_key key = {};
bcmolt_device_nni_speed nni_speed_cfg;
bcmolt_device_cfg dev_cfg;
bcmolt_iwf_mode iwf_mode;
uint32_t logical_pon;
if (BCMOS_TRUE == BCMBAL_CFG_PROP_IS_SET(&(p_acc_term->api_req_acc_term_obj_info), access_terminal, iwf_mode))
{
iwf_mode = bal_iwf_mode2iwf_mode(p_acc_term->api_req_acc_term_obj_info.data.iwf_mode);
}
else
{
iwf_mode = BCMOLT_IWF_MODE_DIRECT_MAPPING_MODE;
}
BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon)
{
mac_util_topo_pon_context *topo_context, *old_topo_context;
old_topo_context = bcm_topo_pon_get_context(logical_pon, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
if (old_topo_context)
bcmos_free(old_topo_context);
topo_context = bcmos_calloc(sizeof(*topo_context));
topo_context->iwf_mode = iwf_mode;
bcm_topo_pon_set_context(logical_pon, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL, topo_context);
}
BCMOLT_CFG_INIT(&dev_cfg, device, key);
BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, acc_term_connectivity.devices[device_id].system_mode);
#ifdef QAX_SWITCH
/* until speed is configurable through topology settings hardcode it based on switch type */
BCM_LOG(INFO, log_id_mac_util, "nni speed is: 10G\n");
nni_speed_cfg.first_half = BCMOLT_NNI_SPEED_GBPS_10;
nni_speed_cfg.second_half = BCMOLT_NNI_SPEED_GBPS_10;
BCMOLT_CFG_PROP_SET(&dev_cfg, device, nni_speed, nni_speed_cfg);
#endif
return bcmolt_cfg_set(device_id, &dev_cfg.hdr);
}
/**
* @brief access terminal set for gpon_16
*/
bcmos_errno mac_util_access_terminal_set_for_gpon_16 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
{
bcmos_errno rc;
rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
if (rc != BCM_ERR_OK)
return rc;
rc = mac_util_access_terminal_set_for_gpon(p_acc_term, op_type, BCMOLT_SYSTEM_MODE_GPON__16_X, device_id);
if (rc != BCM_ERR_OK)
return rc;
return maple_access_terminal_connect_common(device_id);
}
/**
* @brief access terminal set for gpon_8
*/
bcmos_errno mac_util_access_terminal_set_for_gpon_8 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
{
bcmos_errno rc;
rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
if (rc != BCM_ERR_OK)
return rc;
rc = mac_util_access_terminal_set_for_gpon(p_acc_term, op_type, BCMOLT_SYSTEM_MODE_GPON__8_X, device_id);
if (rc != BCM_ERR_OK)
return rc;
return maple_access_terminal_connect_common(device_id);
}
/**
* @brief post access terminal up configurations on Maple
*/
bcmos_errno mac_util_access_terminal_post_indication_set_for_gpon(bcmolt_devid device_id)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_devid dummy;
uint32_t physical_if_id;
uint32_t logical_pon = BCM_TOPO_PON_INVALID;
bcmolt_gpon_ni_key ni_key = {};
bcmolt_gpon_ni_cfg ni_cfg = {};
bcmolt_gpon_sn_acquisition sn_acquisition_cfg = {};
bcmolt_gpon_ni_auto_cfg gpon_ni_auto_cfg = {}; /* main auto cfg api struct */
/* configure one time settings for all the interfaces on this device */
BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon)
{
/* get physical interface from logical interface */
rc = bcm_topo_pon_get_logical2physical (logical_pon, &dummy, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
break;
}
ni_key.pon_ni = physical_if_id;
/* Set the SN acquisition mode to enable */
BCMOLT_CFG_INIT(&ni_cfg, gpon_ni, ni_key);
sn_acquisition_cfg.control = BCMOLT_CONTROL_STATE_ENABLE;
sn_acquisition_cfg.interval = 5000;
sn_acquisition_cfg.onu_post_discovery_mode = BCMOLT_ONU_POST_DISCOVERY_MODE_NONE;
BCMOLT_CFG_PROP_SET(&ni_cfg, gpon_ni, sn_acquisition, sn_acquisition_cfg);
rc = bcmolt_cfg_set(device_id, &ni_cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Failed to set sn acquisition configuration (%s), err_text=%s)\n",
bcmos_strerror(rc), ni_cfg.hdr.hdr.err_text);
break;
}
/* turn off the auto indication messages for gpon_ni.serial_number_acquisition_cycle_start */
BCMOLT_AUTO_CFG_INIT(&gpon_ni_auto_cfg, gpon_ni, ni_key);
BCMOLT_AUTO_CFG_PROP_SET(&gpon_ni_auto_cfg, gpon_ni, serial_number_acquisition_cycle_start, BCMOS_FALSE);
rc = bcmolt_auto_cfg_set(device_id, &gpon_ni_auto_cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"bcmolt_auto_cfg_set for gpon_ni.serial_number_acquisition_cycle_start, Failed (%s), err_text=%s)\n",
bcmos_strerror(rc), gpon_ni_auto_cfg.hdr.hdr.err_text);
/* ignore any error, just continue anyway */
}
}
return rc;
}
/**
* @brief Command Set setup routine for interface up to mac application for GPON
*
* This routine is called by if_fsm in the BAL core to initialize the command
* set to up the interface of the mac application. The cmdset actually
* consists of two commands, one is to send the if up request message to the mac
* App and handle the relevant response, the other is to handle the indication message
* from the mac APP when the operation is completed.
*
* @param p_interface_inst Pointer to interface instance
* @param op_type Operation type on access terminal/interface instance
*
* @return bcmos_errno
*
*/
bcmos_errno mac_util_interface_set_for_gpon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type)
{
bcmos_errno rc = BCM_ERR_OK;
bcmbal_interface_cfg *p_interface_req = &(p_interface_inst->api_req_int_obj_info);
bcmbal_interface_key intf_key = p_interface_req->key;
mac_util_topo_pon_context *topo_context;
do
{
bcmolt_devid device_id;
uint32_t physical_if_id;
/* get physical interface from logical interface */
rc = bcm_topo_pon_get_logical2physical (intf_key.intf_id, &device_id, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
break;
}
bcmolt_gpon_ni_set_pon_state oper_ni;
bcmolt_gpon_ni_key ni_key = { .pon_ni = physical_if_id };
bcmolt_gpon_trx_cfg cfg = {};
bcmolt_gpon_trx_key trx_key = { .pon_ni = physical_if_id };
bcmolt_trx_type trx_type;
bcmolt_gpon_iwf_key iwf_key = { .pon_ni = physical_if_id };
bcmolt_gpon_iwf_cfg iwf_cfg = {};
bcmolt_mac_table_configuration mac_table_configuration = {};
if (BAL_UTIL_OPER_IF_UP == op_type)
{
/* set the pon_ni transceiver configuration */
BCMOLT_CFG_INIT(&cfg, gpon_trx, trx_key);
/* If the user didn't specify a transceiver, then use the default */
if (BCMOS_TRUE != BCMBAL_CFG_PROP_IS_SET(p_interface_req, interface, transceiver_type))
{
/* The user didn't choose a transceiver type, so override it here
* with the default value for GPON
*/
BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_GPON);
}
/* Set the (default or chosen) transceiver configuration into the MAC device */
trx_type = mac_gpon_bal_trx_type2bcm68620_trx_type(p_interface_req->data.transceiver_type, intf_key.intf_id);
BCMOLT_CFG_PROP_SET(&cfg, gpon_trx, transceiver_type, trx_type);
rc = bcmolt_cfg_set(device_id, &cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
"Failed to set trx configuration (%s), err_text=%s\n", bcmos_strerror(rc), cfg.hdr.hdr.err_text);
break;
}
/* Configure pon_ni interworking and mac table configuration based on the system global interworking mode
*
* We only have to change the mode if the user has chosen per-flow, because direct mode is the default
* iwf mode in MAPLE
*/
topo_context = bcm_topo_pon_get_context(intf_key.intf_id, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
{
/* set the iwf configuration */
BCMOLT_CFG_INIT(&iwf_cfg, gpon_iwf, iwf_key);
BCMOLT_CFG_PROP_SET(&iwf_cfg, gpon_iwf, iwf_mode, BCMOLT_IWF_MODE_PER_FLOW_MODE);
/* set the mac table configuration */
mac_table_configuration.aging_time = 10000;
mac_table_configuration.automatic_mac_move = BCMOLT_CONTROL_STATE_DISABLE;
mac_table_configuration.automatic_static_mode = BCMOLT_CONTROL_STATE_DISABLE;
mac_table_configuration.default_flow_id = 0;
mac_table_configuration.learning_mode = BCMOLT_MAC_TABLE_LEARNING_MODE_NORMAL;
mac_table_configuration.miss_fallback = BCMOLT_MAC_TABLE_MISS_FALLBACK_DROP;
mac_table_configuration.automatic_mac_learning = BCMOLT_CONTROL_STATE_ENABLE;
mac_table_configuration.automatic_mac_aging = BCMOLT_CONTROL_STATE_ENABLE;
BCMOLT_CFG_PROP_SET(&iwf_cfg, gpon_iwf, mac_table_configuration, mac_table_configuration);
rc = bcmolt_cfg_set(device_id, &iwf_cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
"Failed to set iwf / mac table configuration (%s), err_text=%s)\n",
bcmos_strerror(rc), iwf_cfg.hdr.hdr.err_text);
break;
}
}
}
/* invoke the pon_ni state change to the requested state */
BCMOLT_OPER_INIT(&oper_ni, gpon_ni, set_pon_state, ni_key);
BCMOLT_OPER_PROP_SET(&oper_ni, gpon_ni, set_pon_state, pon_state,
(BAL_UTIL_OPER_IF_UP == op_type) ?
BCMOLT_PON_OPERATION_ACTIVE_WORKING : BCMOLT_PON_OPERATION_INACTIVE);
rc = bcmolt_oper_submit(device_id, &oper_ni.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
"Failed to %s (submit) pon interface (%s), err_text=%s\n",
(BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate",
bcmos_strerror(rc), oper_ni.hdr.hdr.err_text);
}
} while (0);
if (BCM_ERR_OK == rc)
{
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id),
"Submitted INTERFACE-%s operation for IF %d\n",
(BAL_UTIL_OPER_IF_UP == op_type) ? "UP" : "DOWN",
intf_key.intf_id);
}
return rc;
}
/**
* @brief maple_mac_ds_iwf_cfg
*
* This routine is used to configure the relevant downstream ingress and egress iwf at the device
*
* @param p_flow Pointer to the flow info
* @param per_flow_mode_vlan_id vlan id for GEM port mapping in per flow mode
* @param is_pbit_enabled Flag indicating whether or not to resolve pbits to GEM IDs
*
* @return bcmos_errno
*/
static bcmos_errno maple_mac_ds_iwf_cfg(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id, bcmos_bool is_pbit_enabled)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_iwf_ds_ingress_flow_key in_key = {};
bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg = {};
bcmolt_gpon_iwf_ds_egress_flow_key egr_key = {};
bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
do
{
/* get physical interface from logical interface */
rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
break;
}
/* configure the new ds ingress flow */
in_key.pon_ni = physical_if_id;
in_key.vlan_id = per_flow_mode_vlan_id;
BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
if (BCMOS_TRUE == p_flow->data.resolve_mac)
{
/* mapping method */
BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_method,
BCMOLT_VLAN_TO_FLOW_MAPPING_METHOD_MACPLUSVID);
}
else
{
/* mapping method */
BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_method,
BCMOLT_VLAN_TO_FLOW_MAPPING_METHOD_VID);
}
/* mapping tag */
BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, mapping_tag,
BCMOLT_MAPPING_TAG_METHOD_OUTER_VID);
BCMOLT_CFG_PROP_SET(&in_cfg, gpon_iwf_ds_ingress_flow, vlan_action, BCMOLT_DS_VLAN_ACTION_TRANSPARENT);
rc = bcmolt_cfg_set(device_id, &in_cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to configure ingress flow pon_ni = %d vlan_id = %d rc = %s (%d), err_text=%s\n",
in_key.pon_ni,
in_key.vlan_id,
bcmos_strerror(rc),
rc,
in_cfg.hdr.hdr.err_text);
break;
}
/* configure the new ds egress flow */
egr_key.pon_ni = physical_if_id;
egr_key.flow_id = p_flow->data.svc_port_id;
/* Configure DS egress handling: flow -> GEM */
BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, gem_port, p_flow->data.svc_port_id);
BCMOLT_CFG_PROP_SET(&egr_cfg, gpon_iwf_ds_egress_flow, pbit_control, is_pbit_enabled);
rc = bcmolt_cfg_set(device_id, &egr_cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to configure egress flow pon_ni = %d flow_id = %d rc = %s (%d), err_text=%s\n",
egr_key.pon_ni,
egr_key.flow_id,
bcmos_strerror(rc),
rc,
egr_cfg.hdr.hdr.err_text);
}
} while (0);
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"going out of %s rc = %s (%d)\n",
__FUNCTION__,
bcmos_strerror(rc), rc);
return rc;
}
/**
* @brief maple_mac_ds_iwf_cfg_remove
*
* This routine is used to remove configuration from Maple of the relevant downstream ingress and egress iwf
*
* @param p_flow Pointer to the flow info
* @param per_flow_mode_vlan_id vlan id for per flow mode
*
* @return bcmos_errno
*/
static bcmos_errno maple_mac_ds_iwf_cfg_remove(bcmbal_flow_cfg *p_flow, uint16_t per_flow_mode_vlan_id)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_iwf_ds_ingress_flow_key in_key = {};
bcmolt_gpon_iwf_ds_ingress_flow_cfg in_cfg = {};
bcmolt_gpon_iwf_ds_egress_flow_key egr_key = {};
bcmolt_gpon_iwf_ds_egress_flow_cfg egr_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
do
{
/* config clear ds ingress flow */
rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
break;
}
in_key.pon_ni = physical_if_id;
in_key.vlan_id = per_flow_mode_vlan_id;
BCMOLT_CFG_INIT(&in_cfg, gpon_iwf_ds_ingress_flow, in_key);
rc = bcmolt_cfg_clear(device_id, &in_cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to Clear ingress flow pon_ni = %d vlan_id = %d rc = %s (%d)\n",
in_key.pon_ni,
in_key.vlan_id,
bcmos_strerror(rc),
rc);
break;
}
/* config clear ds egress flow */
egr_key.pon_ni = physical_if_id;
egr_key.flow_id = p_flow->data.svc_port_id;
/* Configure DS egress handling: flow -> GEM */
BCMOLT_CFG_INIT(&egr_cfg, gpon_iwf_ds_egress_flow, egr_key);
rc = bcmolt_cfg_clear(device_id, &egr_cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to Clear egress flow pon_ni = %d flow_id = %d rc = %s (%d)\n",
egr_key.pon_ni,
egr_key.flow_id,
bcmos_strerror(rc),
rc);
}
} while (0);
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"%s: config clear: rc = %s (%d)\n",
__FUNCTION__,
bcmos_strerror(rc), rc);
return rc;
}
/**
* @brief maple_mac_us_iwf_cfg
*
* This routine is used to configure the relevant upstream iwf at the device
*
* @param p_flow A pointer to a flow object
*
* @param pbit A pbit value being configured for the specified flow
*
* @return bcmos_errno
*/
static bcmos_errno maple_mac_us_iwf_cfg(bcmbal_flow_cfg *p_flow, uint8_t pbit)
{
bcmos_errno rc = BCM_ERR_PARM;
bcmolt_gpon_iwf_us_flow_key us_key = {};
bcmolt_gpon_iwf_us_flow_cfg us_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
/* get physical interface from logical interface */
rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
}
else
{
/* configure the related iwf us flow */
us_key.pon_ni = physical_if_id;
us_key.gem_port_id = p_flow->data.svc_port_id;
BCMOLT_CFG_INIT(&us_cfg, gpon_iwf_us_flow, us_key);
BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, flow_id, p_flow->data.svc_port_id);
if (BCMOS_TRUE == p_flow->data.resolve_mac)
{
BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, mac_learning, BCMOS_TRUE);
}
else
{
BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, mac_learning, BCMOS_FALSE);
}
BCMOLT_CFG_PROP_SET(&us_cfg, gpon_iwf_us_flow, vlan_action, BCMOLT_US_VLAN_ACTION_TRANSPARENT);
rc = bcmolt_cfg_set(device_id, &us_cfg.hdr);
}
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"%s FAILED, rc = %s (%d), err_text = %s\n",
__FUNCTION__,
bcmos_strerror(rc), rc, us_cfg.hdr.hdr.err_text);
}
return rc;
}
/**
* @brief maple_mac_us_iwf_cfg_remove
*
* This routine is used to remove configuration from Maple of the relevant upstream iwf
*
* @param p_flow A pointer to a flow object
*
* @return bcmos_errno
*/
static bcmos_errno maple_mac_us_iwf_cfg_remove(bcmbal_flow_cfg *p_flow)
{
bcmos_errno rc = BCM_ERR_PARM;
bcmolt_gpon_iwf_us_flow_key us_key = {};
bcmolt_gpon_iwf_us_flow_cfg us_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
/* configure the related iwf us flow */
rc = bcm_topo_pon_get_logical2physical (p_flow->data.access_int_id, &device_id, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
return rc;
}
us_key.pon_ni = physical_if_id;
us_key.gem_port_id = p_flow->data.svc_port_id;
BCMOLT_CFG_INIT(&us_cfg, gpon_iwf_us_flow, us_key);
rc = bcmolt_cfg_clear(device_id, &us_cfg.hdr);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow->data.access_int_id),
"%s FAILED, rc = %s (%d)\n",
__FUNCTION__,
bcmos_strerror(rc), rc);
}
return rc;
}
/**
* @brief mac_util_validate_subscriber_terminal_info_for_gpon
*
* This routine is used to validate all input attributes required for a sub term setting
* received from core for GPON
*
* @param p_sub_term_req A pointer to a subscriber terminal object
*
* @return bcmos_errno
*/
bcmos_errno mac_util_validate_subscriber_terminal_info_for_gpon(const bcmbal_subscriber_terminal_cfg *p_sub_term_req)
{
if(BCMBAL_STATE_UP == p_sub_term_req->data.admin_state)
{
if (!BCMBAL_CFG_PROP_IS_SET (p_sub_term_req, subscriber_terminal, serial_number))
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Serial number is a mandatory parameter for a gpon subscriber terminal, and it is not set\n");
return BCM_ERR_MANDATORY_PARM_IS_MISSING;
}
if (!BCMBAL_CFG_PROP_IS_SET(p_sub_term_req, subscriber_terminal, password))
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Password is a mandatory parameter for a gpon subscriber terminal, and it is not set\n");
return BCM_ERR_MANDATORY_PARM_IS_MISSING;
}
}
return BCM_ERR_OK;
}
/**
* @brief Command Set setup routine for subscriber terminal connect to mac application for GPON
*
* This routine is called by sub_term_fsm in the BAL core to initialize the command
* set to connect the subscriber terminal of the mac application. The cmdset actually
* consists of two commands, one is to send the sub_term request message to the mac
* App and handle the relevant response, the other is to handle the indication message
* from the mac APP when the operation is completed.
*
* @param p_sub_term_inst A pointer to a subscriber terminal instance
* @param op_type Type of operation being performed on the subscriber terminal instance
* @param is_post_discovery Used for ADD, indicates if this is a request after a ONU discovery
*
* @return bcmos_errno
*
* @note we configure Maple for ONU in 2 stages:
* \li Stage 1: do cfg_set with the serial num, password, omci port, as part of first sub_term_set from Core
* \li Stage 2: set the ONU state to ACTIVE using oper_submit, as part of second sub_term_set from Core (after
* receiving a Discovery indication)
*/
bcmos_errno mac_util_subscriber_terminal_set_for_gpon(sub_term_inst *p_sub_term_inst, bal_util_oper_sub_term op_type, bcmos_bool is_post_discovery)
{
bcmos_errno rc = BCM_ERR_OK;
bcmbal_subscriber_terminal_cfg *p_sub_term_req = &p_sub_term_inst->api_req_sub_term_info;
do
{
bcmolt_devid device_id;
uint32_t physical_if_id;
/* get physical interface from logical interface */
rc = bcm_topo_pon_get_logical2physical (p_sub_term_req->key.intf_id, &device_id, &physical_if_id);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc));
break;
}
bcmolt_gpon_onu_cfg cfg = {};
bcmolt_gpon_onu_cfg onu_cfg_get = {};
bcmolt_gpon_onu_set_onu_state oper = {};
bcmolt_gpon_onu_key key = {};
bcmolt_onu_operation new_onu_state;
bcmolt_gpon_onu_auto_cfg gpon_onu_auto_cfg = {}; /* main auto cfg api struct */
/* set the onu key - set it to the physical if id */
key.pon_ni = physical_if_id;
key.onu_id = p_sub_term_req->key.sub_term_id;
/* set the onu key */
BCMOLT_CFG_INIT(&cfg, gpon_onu, key);
/* invoke onu state change operation to the new state */
BCMOLT_OPER_INIT(&oper, gpon_onu, set_onu_state, key);
if(BAL_UTIL_OPER_SUB_TERM_CLEAR == op_type)
{
/* Delete the configuration of the ONU */
rc = bcmolt_cfg_clear(device_id, &cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Failed to clear onu configuration(%s)\n",
bcmos_strerror(rc));
}
/* No indication from Maple will result from the clear operation
* so fake it here
*/
mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
p_sub_term_req->key.sub_term_id,
(bcmolt_serial_number *)NULL,
BAL_UTIL_OPER_SUB_TERM_CLEAR,
rc, rc,
MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
/* No further processing is required for the CLEAR operation */
break;
}
else if(BAL_UTIL_OPER_SUB_TERM_ADD == op_type)
{
/* first do a get, to see if onu is in active state already */
BCMOLT_CFG_INIT(&onu_cfg_get, gpon_onu, key);
BCMOLT_CFG_PROP_GET(&onu_cfg_get, gpon_onu, onu_state);
rc = bcmolt_cfg_get(device_id, &onu_cfg_get.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Failed to get onu configuration(%s), err_text=%s, ... continue to configure\n",
bcmos_strerror(rc), onu_cfg_get.hdr.hdr.err_text);
/* don't break, but continue with the set anyways */
}
else
{
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"%s: ONU state = %d, [pon_ni=%d, onu_id=%d], BEFORE doing cfg_set on Maple\n",
__FUNCTION__, onu_cfg_get.data.onu_state, onu_cfg_get.key.pon_ni, onu_cfg_get.key.onu_id);
}
if ((BCM_ERR_OK == rc) && (BCMOLT_ONU_STATE_ACTIVE == onu_cfg_get.data.onu_state))
{
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"%s: ONU already in active state during ADD. Skipping further config\n",
__FUNCTION__);
mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
p_sub_term_req->key.sub_term_id,
(bcmolt_serial_number *)NULL,
BAL_UTIL_OPER_SUB_TERM_ADD,
rc, rc,
BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
break;
}
/* set the sn & password only if it being configured for the first time */
if (BCMOS_FALSE == is_post_discovery)
{
BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, serial_number,
*((bcmolt_serial_number *)&p_sub_term_req->data.serial_number));
BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, password,
*((bcmolt_arr_u8_10 *)&p_sub_term_req->data.password));
/* set the onu configuration */
BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, auto_password_learning, BCMOS_TRUE);
BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, us_fec, BCMOS_FALSE);
/* set the onu management channel port */
BCMOLT_CFG_PROP_SET(&cfg, gpon_onu, omci_port_id, p_sub_term_req->data.svc_port_id);
rc = bcmolt_cfg_set(device_id, &cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Failed to set onu configuration(%s), err_text=%s\n",
bcmos_strerror(rc), cfg.hdr.hdr.err_text);
break;
}
/**
* @note If this is first time set for ADD, then skip setting the ONU state for now.
* Wait until ONU Discovery is received.
*/
break;
}
/* turn off the auto indication messages for gpon_onu.rei */
BCMOLT_AUTO_CFG_INIT(&gpon_onu_auto_cfg, gpon_onu, key);
BCMOLT_AUTO_CFG_PROP_SET(&gpon_onu_auto_cfg, gpon_onu, rei, BCMOS_FALSE);
rc = bcmolt_auto_cfg_set(device_id, &gpon_onu_auto_cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"bcmolt_auto_cfg_set for gpon_onu.rei Failed (%s), err_text=%s)\n",
bcmos_strerror(rc), gpon_onu_auto_cfg.hdr.hdr.err_text);
/* This is not fatal, so just continue anyway */
}
/*
* Set the new onu state for the ADD operation
*/
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Setting ONU state to active\n");
new_onu_state = BCMOLT_ONU_OPERATION_ACTIVE;
}
else if (BAL_UTIL_OPER_SUB_TERM_REMOVE == op_type)
{
/* If the ONU is not present, then it will never respond to the deactivate command
* with an indication, so just allow the FSM to continue as if it did.
*/
if(BCMBAL_STATUS_NOT_PRESENT != p_sub_term_inst->current_sub_term_info.data.oper_status)
{
/*
* Set the new onu state for the REMOVE operation
*/
BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Setting ONU state to IN-active\n");
new_onu_state = BCMOLT_ONU_OPERATION_INACTIVE;
}
}
else /* This should never happen */
{
BCM_LOG(ERROR, log_id_mac_util, "Bad request from core\n");
rc = BCM_ERR_INTERNAL;
break;
}
/* Do oper_submit to set the ONU state */
BCMOLT_OPER_PROP_SET(&oper, gpon_onu, set_onu_state, onu_state, new_onu_state);
rc = bcmolt_oper_submit(device_id, &oper.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"bcmolt_oper_submit Failed for onu state Failed (%s), err_text=%s\n",
bcmos_strerror(rc), &(oper.hdr.hdr.err_text[0]));
}
/* If the ONU is not present, then it will never respond to the deactivate command
* with an indication, so just allow the FSM to continue as if it did.
*/
if((BCMOLT_ONU_OPERATION_INACTIVE == new_onu_state) &&
(BCMBAL_STATUS_NOT_PRESENT == p_sub_term_inst->current_sub_term_info.data.oper_status))
{
mac_util_report_sub_term_event(p_sub_term_req->key.intf_id,
p_sub_term_req->key.sub_term_id,
(bcmolt_serial_number *)NULL,
BAL_UTIL_OPER_SUB_TERM_REMOVE,
rc, rc,
MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
}
} while (0);
if (rc == BCM_ERR_STATE)
{
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"%s failed to set state, possibly because interface is not configured yet, pon fiber disconnect, or onu disconnect: rc = %s (%d)\n",
__FUNCTION__,
bcmos_strerror(rc), rc);
}
else if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"%s Failed: rc = %s (%d)\n",
__FUNCTION__,
bcmos_strerror(rc), rc);
}
return rc;
}
/**
* @brief validate_flow_info for gpon
*
* This routine is used to validate all input attributes required for a flow
* setting received from core for GPON
*
* @param p_flow_req A pointer to a flow object
*
* @return bcmos_errno
*/
bcmos_errno mac_util_validate_flow_info_for_gpon (const bcmbal_flow_cfg *p_flow_req)
{
bcmos_errno rc = BCM_ERR_OK;
mac_util_topo_pon_context *topo_context;
topo_context = bcm_topo_pon_get_context(p_flow_req->data.access_int_id, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
if ((BCM_ERR_OK == rc) && (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode))
{
if (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, o_vid))
{
/* if the flow has an action to remove the outer tag from a double tagged OLT downstream packets,
the outer tag will be removed by the SWITCH in front of the MAC, the MAC should take the inner
tag vid for GEM decision. Sep-28-2015 IL
*/
if (BCMOS_TRUE == mac_util_check_flow_is_double_tag_remove_o_tag (p_flow_req))
{
if (BCMOS_TRUE != BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, i_vid))
{
BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"classifier i_vid id is a mandatory downstream parameter for double tagged action, "
"and it is not set\n");
rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
}
}
}
else
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"o_vid id is a mandatory parameter for a flow classifier, and it is not set\n");
rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
}
}
if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM)
{
if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, agg_port_id))
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"agg port id is a mandatory parameter for an US flow, and it is not set\n");
rc = BCM_ERR_MANDATORY_PARM_IS_MISSING;
}
}
return rc;
}
/**
* @brief flow set for GPON
*
* @param p_flow_req pointer to flow request structure from core
* @param op_type ADD, REMOVE or CLEAR
* @param p_flow_core local DB flow context passed as a cookie
*
* @return errno error
*/
bcmos_errno mac_util_flow_set_for_gpon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
{
bcmos_errno rc = BCM_ERR_OK;
bcmos_bool is_pbit_enabled = BCMOS_FALSE;
uint16_t per_flow_mode_vlan_id = 0; /* hold the value of the vlan tag to use in per-flow mode */
uint8_t pbits_val = 0;
mac_util_topo_pon_context *topo_context;
flow_list_entry *p_mac_util_flow_entry = NULL;
topo_context = bcm_topo_pon_get_context(p_flow_req->data.access_int_id, BCM_TOPO_PON_CONTEXT_ID_MAC_UTIL);
if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
{
per_flow_mode_vlan_id = 0; /* set to default */
if (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, o_vid))
{
/* if the flow has an action to remove the outer tag from a double tagged OLT downstream packets,
the outer tag will be removed by the SWITCH in front of the MAC, the MAC should take the inner
tag vid for GEM decision. Sep-28-2015 IL
*/
if (BCMOS_TRUE == mac_util_check_flow_is_double_tag_remove_o_tag (p_flow_req))
{
if (BCMOS_TRUE == BCMBAL_ATTRIBUTE_PROP_IS_SET(&(p_flow_req->data.classifier), classifier, i_vid))
{
per_flow_mode_vlan_id = p_flow_req->data.classifier.i_vid;
}
//else should not happen here really, since this was validated in a previous step
}
else
{
per_flow_mode_vlan_id = p_flow_req->data.classifier.o_vid;
}
}
//else should not happen here really, since this was validated in a previous step
}
/* Check the operation id */
if ((BAL_UTIL_OPER_FLOW_ADD != op_type) &&
(BAL_UTIL_OPER_FLOW_REMOVE != op_type) &&
(BAL_UTIL_OPER_FLOW_CLEAR != op_type))
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"Unexpected mac_util flow operation %d \n", op_type);
return BCM_ERR_PARM;
}
/* flow Add or Modify */
if (BAL_UTIL_OPER_FLOW_ADD == op_type)
{
switch (p_flow_req->key.flow_type)
{
/* unicast flows */
case BCMBAL_FLOW_TYPE_UPSTREAM:
case BCMBAL_FLOW_TYPE_DOWNSTREAM:
{
if (p_flow_req->data.classifier.o_pbits)
{
/* o_pbits can only take one p-bit value */
pbits_val = p_flow_req->data.classifier.o_pbits;
is_pbit_enabled = BCMOS_TRUE;
}
else
{
pbits_val = 0;
is_pbit_enabled = BCMOS_FALSE;
}
/* create a gem port id and relevant flow for a single pbit, or with no pbit */
/* pass on the op type also to specify if it is FLOW_ADD OR FLOW_MODIFY */
rc = maple_mac_unicast_flow_add(p_flow_req, pbits_val, per_flow_mode_vlan_id, op_type, &p_mac_util_flow_entry);
if ((BCM_ERR_OK != rc) || (NULL == p_mac_util_flow_entry))
{
break;
}
/* configure iwf flows in case of per flow interworking mode */
if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
{
if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type)
{
rc = maple_mac_ds_iwf_cfg(p_flow_req, per_flow_mode_vlan_id, is_pbit_enabled);
}
else
/* FLOW_TYPE_UPSTREAM */
{
rc = maple_mac_us_iwf_cfg(p_flow_req, pbits_val);
}
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"Failed to add iwf flows in per flow mode (%s))\n",
bcmos_strerror(rc));
break;
}
}
/* mark flow configuration to device completed */
mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
}
break;
case BCMBAL_FLOW_TYPE_BROADCAST:
{
rc = maple_mac_broadcast_flow_add(p_flow_req, per_flow_mode_vlan_id, op_type, &p_mac_util_flow_entry);
if ((BCM_ERR_OK != rc) || (NULL == p_mac_util_flow_entry))
{
break;
}
}
break;
default:
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"Unknown flow type %d\n",
p_flow_req->key.flow_type);
rc = BCM_ERR_PARM;
break;
}
}
else if ((BAL_UTIL_OPER_FLOW_REMOVE == op_type) ||
(BAL_UTIL_OPER_FLOW_CLEAR == op_type))
{
/* find the flow */
p_mac_util_flow_entry = _mac_util_db_flow_get_w_flow_key(p_flow_req->data.access_int_id, &(p_flow_req->key));
if (NULL == p_mac_util_flow_entry)
{
rc = BCM_ERR_NOENT;
if (BAL_UTIL_OPER_FLOW_CLEAR != op_type)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"%s: NULL mac util flow entry to remove: flow id: %d, flow_type: %s\n",
__FUNCTION__,
p_flow_req->key.flow_id,
(p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ? "up":"down"));
}
goto exit;
}
switch (p_flow_req->key.flow_type)
{
/* unicast flows */
case BCMBAL_FLOW_TYPE_UPSTREAM:
case BCMBAL_FLOW_TYPE_DOWNSTREAM:
{
/* First De-configure IWF flows in case of per flow interworking mode */
if (BCMOLT_IWF_MODE_PER_FLOW_MODE == topo_context->iwf_mode)
{
if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type)
{
rc = maple_mac_ds_iwf_cfg_remove(p_flow_req, per_flow_mode_vlan_id);
}
else
{
rc = maple_mac_us_iwf_cfg_remove(p_flow_req);
}
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"Failed to remove iwf flows in per flow mode (%s))\n",
bcmos_strerror(rc));
break;
}
}
/** Then remove unicast GEM/Alloc Id from Maple and flow entry from local database */
rc = maple_mac_unicast_flow_remove(p_flow_req, op_type, p_mac_util_flow_entry);
if (BCM_ERR_OK != rc)
{
break;
}
/* mark flow De-configuration to device completed */
mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
}
break;
case BCMBAL_FLOW_TYPE_BROADCAST:
{
rc = maple_mac_broadcast_flow_remove(p_flow_req, per_flow_mode_vlan_id, op_type, p_mac_util_flow_entry);
}
break;
default:
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"Unknown flow type %d\n",
p_flow_req->key.flow_type);
rc = BCM_ERR_PARM;
break;
}
}
else
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id),
"Unknown flow op type %d for flow id/type = %d/%d\n",
op_type, p_flow_req->key.flow_id, p_flow_req->key.flow_type);
rc = BCM_ERR_PARM;
}
exit:
if (BCM_ERR_OK == rc)
{
/*
* Check flow entry flags to see if an indication to Core should be triggered immediately:
* (Special handling for flow configuration, for the case no device configuration is needed,
* and/or no indication from device is expected - could be the case of a single/multiple
* gem ports used for us and ds, and us was already configured.
* - send the flow ind immediately
*/
check_send_flow_bal_ind_msg(p_mac_util_flow_entry, BCM_ERR_OK, BCMOLT_RESULT_SUCCESS);
}
else
{
if ((BCM_ERR_NOENT == rc) && (BAL_UTIL_OPER_FLOW_CLEAR == op_type))
{
/*
* For flow CLEAR, and if no flow entry is found, then fake an indication success to Core,
* for it to execute the flow state machine.
* The reasons for flow entry not found could be because the flow was already admin-ed Down.
* Admin-down of a flow causes mac util to clear flow config and flow instance from itself
* and the maple HW. However, Core FSM still keeps it's flow instance during admin down state.
*/
mac_util_report_flow_remove_success (p_flow_req->key, p_flow_req->data.access_int_id, op_type);
rc = BCM_ERR_OK;
}
}
//else if there was an error during config, just return a failure; no need to send back indication for that.
return rc;
}
bcmos_errno maple_gpon_mac_check_gem_port_id(uint32_t if_id, uint32_t onu_id, uint16_t svc_port_id,
bcmos_bool *is_configured, bcmos_bool *is_activated)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_gem_port_key gem_key = {};
bcmolt_gpon_gem_port_cfg gem_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
/* set the gem port object key */
gem_key.pon_ni = physical_if_id;
gem_key.gem_port_id = svc_port_id;
BCMOLT_CFG_INIT(&gem_cfg, gpon_gem_port, gem_key);
BCMOLT_CFG_PROP_GET(&gem_cfg, gpon_gem_port, all_properties);
rc = bcmolt_cfg_get(device_id, &gem_cfg.hdr);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"%s FAILED in bcmolt_cfg_get: svc_port_id = %d if_id = %d onu_id = %d\n",
__FUNCTION__,
svc_port_id, if_id, onu_id);
return rc;
}
/* may be configured; does gem belong to same onu ? */
if (BCMOLT_GPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state && onu_id != gem_cfg.data.onu_id)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"%s FAILED, onu id mismatch: svc_port_id = %d if_id = %d is already assigned to onu_id = %d (not to onu id %d) \n",
__FUNCTION__,
svc_port_id, if_id, gem_cfg.data.onu_id, onu_id);
return BCM_ERR_PARM;
}
*is_configured = BCMOLT_GPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state;
*is_activated = BCMOLT_GPON_GEM_PORT_STATE_ACTIVE == gem_cfg.data.gem_port_state;
return rc;
}
bcmos_errno maple_gpon_gem_port_id_add(uint32_t if_id, uint16_t svc_port_id, uint32_t onu_id, bcmolt_gem_port_configuration *configuration)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_gem_port_key gem_key = {};
bcmolt_gpon_gem_port_cfg gem_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
/* set the gem port object key */
gem_key.pon_ni = physical_if_id;
gem_key.gem_port_id = svc_port_id;
BCMOLT_CFG_INIT(&gem_cfg, gpon_gem_port, gem_key);
/* set the gem port configuration */
if (onu_id < MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM)
{
BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, onu_id, onu_id);
BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, upstream_destination_queue,
BCMOLT_US_GEM_PORT_DESTINATION_DATA);
}
BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, downstream_encryption_mode,
BCMOLT_CONTROL_STATE_DISABLE);
BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, configuration, *configuration);
BCMOLT_CFG_PROP_SET(&gem_cfg, gpon_gem_port, control, BCMOLT_CONTROL_STATE_ENABLE);
rc = bcmolt_cfg_set(device_id, &gem_cfg.hdr);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"%s FAILED: rc=%s (%d), svc_port_id = %d dev_id = %d if_id = %d onu_id = %d, err_text=%s\n",
__FUNCTION__,
bcmos_strerror(rc), rc, svc_port_id, device_id, if_id, onu_id, gem_cfg.hdr.hdr.err_text);
}
return rc;
}
bcmos_errno maple_gpon_gem_port_id_remove(uint32_t if_id, uint16_t svc_port_id)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_gem_port_key gem_key = {};
bcmolt_gpon_gem_port_cfg gem_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
gem_key.pon_ni = physical_if_id;
gem_key.gem_port_id = svc_port_id;
BCMOLT_CFG_INIT(&gem_cfg, gpon_gem_port, gem_key);
rc = bcmolt_cfg_clear(device_id, &gem_cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s id=%d, gem=%d, failed with error %s\n",__FUNCTION__, if_id, svc_port_id, bcmos_strerror(rc));
}
return rc;
}
bcmos_errno maple_gpon_mac_get_alloc_id_config (uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_alloc_state *alloc_id_state)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_alloc_key alloc_key = {};
bcmolt_gpon_alloc_cfg alloc_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
/* set the alloc-id key */
alloc_key.pon_ni = physical_if_id;
alloc_key.alloc_id = agg_id;
BCMOLT_CFG_INIT(&alloc_cfg, gpon_alloc, alloc_key);
BCMOLT_CFG_PROP_GET(&alloc_cfg, gpon_alloc, all_properties);
rc = bcmolt_cfg_get(device_id, &alloc_cfg.hdr);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"%s: FAILED in bcmolt_cfg_get rc = %s, agg_id = %d if_id = %d\n",
__FUNCTION__,
bcmos_strerror(rc), agg_id, if_id);
return rc;
}
/* may be configured; does alloc id belong to the expected onu ? */
if (alloc_cfg.data.state != BCMOLT_ALLOC_STATE_NOT_CONFIGURED
&& alloc_cfg.data.onu_id != onu_id)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"%s FAILED, onu id mismatch: agg_id = %d if_id = %d is set to onu %d NOT to onu_id = %d\n",
__FUNCTION__,
agg_id, if_id, alloc_cfg.data.onu_id, onu_id);
return BCM_ERR_PARM;
}
*alloc_id_state = alloc_cfg.data.state;
return BCM_ERR_OK;
}
bcmos_errno maple_gpon_us_alloc_id_add(uint32_t if_id, uint32_t onu_id, uint16_t agg_id, bcmolt_pon_alloc_sla agg_sla)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_alloc_key alloc_key = {};
bcmolt_gpon_alloc_cfg alloc_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
/* set the alloc-id key */
alloc_key.pon_ni = physical_if_id;
alloc_key.alloc_id = agg_id;
BCMOLT_CFG_INIT(&alloc_cfg, gpon_alloc, alloc_key);
BCMOLT_CFG_PROP_SET(&alloc_cfg, gpon_alloc, sla, agg_sla);
/* set the alloc-id - onu assignment */
BCMOLT_CFG_PROP_SET(&alloc_cfg, gpon_alloc, onu_id, onu_id);
rc = bcmolt_cfg_set(device_id, &alloc_cfg.hdr);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"%s: rc = %s, agg_id = %d if_id = %d, err_text = %s \n",
__FUNCTION__,
bcmos_strerror(rc), agg_id, if_id, alloc_cfg.hdr.hdr.err_text);
}
return rc;
}
bcmos_errno maple_gpon_us_alloc_id_remove(uint32_t if_id, uint16_t agg_id)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_gpon_alloc_key alloc_key = {};
bcmolt_gpon_alloc_cfg alloc_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(if_id, device_id, physical_if_id);
/* set the alloc-id key */
alloc_key.pon_ni = physical_if_id;
alloc_key.alloc_id = agg_id;
BCMOLT_CFG_INIT(&alloc_cfg, gpon_alloc, alloc_key);
rc = bcmolt_cfg_clear(device_id, &alloc_cfg.hdr);
if (BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id), "%s failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
}
return rc;
}
/**
* @brief group set for gpon
* @param p_group_req pointer to group request structure from core
* @param op_type ADD, REMOVE or SET
* @param p_group_inst pointer to the Core Group Object instance
*
* @return errno error
*
* @todo shift this out to mac specific files
*/
bcmos_errno mac_util_group_set_for_gpon (bcmbal_group_cfg *p_group_req, bal_util_oper_group op_type, group_inst *p_group_inst)
{
bcmos_errno rc = BCM_ERR_OK;
uint16_t svc_port_id;
uint32_t if_id, i, ref_count;
bcmolt_gem_port_configuration configuration = {0};
/* Check the operation id */
if ((BAL_UTIL_OPER_GROUP_ADD != op_type) &&
(BAL_UTIL_OPER_GROUP_REMOVE != op_type) &&
(BAL_UTIL_OPER_GROUP_SET != op_type))
{
BCM_LOG(ERROR, log_id_mac_util,
"Unexpected mac_util gpon group operation %d \n", op_type);
return BCM_ERR_PARM;
}
configuration.direction = BCMOLT_GEM_PORT_DIRECTION_DOWNSTREAM;
configuration.type = BCMOLT_GEM_PORT_TYPE_MULTICAST;
/* for group SET operation, first remove the old multicast GEM */
if (BAL_UTIL_OPER_GROUP_SET == op_type)
{
bcmbal_group_cfg *p_group_rem_req;
/* use the Core DB for existing members - store in current_flow_info */
p_group_rem_req = &p_group_inst->current_group_info;
for(i=0; i< p_group_rem_req->data.members.len; i++)
{
if_id = p_group_rem_req->data.members.val[i].intf_id;
svc_port_id = p_group_rem_req->data.members.val[i].svc_port_id;
/* svc_port_id can be 0 (not assigned) when group had no owner, no need to remove */
if(svc_port_id)
{
rc = rsc_mgr_gem_get_ref_count(if_id, svc_port_id, &ref_count);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"mac_util gpon group get reference count on interface %d (gem %d) failed \n", if_id, svc_port_id);
return rc;
}
/* if other group is referencing the same GEM (ref_count > 1), do not call Mac API to remove it.
The core will ask Resource Manger to decrease the counter if everything is good */
if ( ref_count == 1)
{
rc = maple_gpon_gem_port_id_remove(if_id, svc_port_id);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"mac_util gpon group set operation SET on remove interface %d (gem %d) failed \n", if_id, svc_port_id);
return rc;
}
}
else if ( ref_count == 0)
{
BCM_LOG(WARNING, log_id_mac_util,
"mac_util gpon group set operation SET on interface %d (gem %d) remove with 0 reference counter \n", if_id, svc_port_id);
}
}
}
}
/* walk through every member interface */
for(i=0; i< p_group_req->data.members.len; i++)
{
if_id = p_group_req->data.members.val[i].intf_id;
svc_port_id = p_group_req->data.members.val[i].svc_port_id;
/* group Add */
if (BAL_UTIL_OPER_GROUP_ADD == op_type || BAL_UTIL_OPER_GROUP_SET == op_type)
{
rc = maple_gpon_gem_port_id_add(if_id, svc_port_id, MAC_UTIL_DUMMY_ONU_ID_FOR_MULTICAST_GEM, &configuration);
}
else if (BAL_UTIL_OPER_GROUP_REMOVE == op_type)
{
rc = rsc_mgr_gem_get_ref_count(if_id, svc_port_id, &ref_count);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"mac_util gpon group operation REM on interface %d (gem %d) failed \n", if_id, svc_port_id);
break;
}
/* if other group is referencing the same GEM (ref_count > 1), do not call Mac API to remove it.
The core will ask Resource Manger to decrease the counter if everything is good */
if ( ref_count == 1)
{
rc = maple_gpon_gem_port_id_remove(if_id, svc_port_id);
}
else if ( ref_count == 0)
{
BCM_LOG(WARNING, log_id_mac_util,
"mac_util gpon group operation REM on interface %d (gem %d) with 0 reference count \n", if_id, svc_port_id);
}
}
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"mac_util gpon group set of operation %d on interface %d (gem %d) failed \n", op_type, if_id, svc_port_id);
break;
}
}
return rc;
}
/*@}*/