blob: a49b3d79c3634fdaff87d34730242a6ebd1c0933 [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_xgpon.c
*
* @brief mac util interfaces definition used by Bal Core, for xgpon
*
* 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_xgpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg);
static bcmos_errno mac_util_indication_handle_for_xgpon_onu (bcmolt_devid device_id, bcmolt_msg *p_msg);
static bcmos_errno mac_util_indication_handle_for_xgpon_alloc_id (bcmolt_devid device_id, bcmolt_msg *p_msg);
/* On XG-PON1 there is no indication such as GEM port configuration completed.
* GEM configuration at the ONU is taken care of completely by OMCI without any PLOAM sent from the OLT
* */
/**
* @brief array stores the list of xgpon (XG-PON1) related auto indications from Maple to subscribe
*/
static mac_util_ind_obj_and_handlers mac_util_xgpon_ind_handlers[] =
{
{BCMOLT_OBJ_ID_XGPON_NI, "BCMOLT_OBJ_ID_XGPON_NI", mac_util_indication_handle_for_xgpon_ni},
{BCMOLT_OBJ_ID_XGPON_ONU, "BCMOLT_OBJ_ID_XGPON_ONU", mac_util_indication_handle_for_xgpon_onu},
{BCMOLT_OBJ_ID_XGPON_ALLOC, "BCMOLT_OBJ_ID_XGPON_ALLOC", mac_util_indication_handle_for_xgpon_alloc_id},
};
/**
* @brief Map bal XGPON transceiver type to bcm68620 transceiver type
*/
static bcmolt_xgpon_trx_type mac_xgpon_bal_trx_type2bcm68620_trx_type(bcmbal_trx_type bal_trx_type)
{
bcmolt_xgpon_trx_type trx_type = BCMOLT_XGPON_TRX_TYPE__NUM_OF;
if (BCMBAL_TRX_TYPE_XGPON_LTH_7222_PC == bal_trx_type)
{
trx_type = BCMOLT_XGPON_TRX_TYPE_LTH_7222_PC;
}
else if (BCMBAL_TRX_TYPE_XGPON_LTH_7226_PC == bal_trx_type)
{
trx_type = BCMOLT_XGPON_TRX_TYPE_LTH_7226_PC;
}
else if (BCMBAL_TRX_TYPE_XGPON_LTH_5302_PC == bal_trx_type)
{
trx_type = BCMOLT_XGPON_TRX_TYPE_LTH_5302_PC;
}
else
{
trx_type = BCMOLT_XGPON_TRX_TYPE_USER_DEFINED;
}
return trx_type;
}
/**
* @brief all the maple indication handlers for xgpon
*
* @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_xgpon (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_xgpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_xgpon_ind_handlers)),
p_msg->group, p_msg->subgroup);
return mac_util_handle_indication(device_id, p_msg, mac_util_xgpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_xgpon_ind_handlers));
}
/**
* @brief Handler function for Maple auto indications for xgpon (XG-PON1) 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_xgpon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg)
{
bcmos_errno rc = BCM_ERR_OK;
uint32_t logical_pon;
do
{
/* PON activation */
if (BCMOLT_XGPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup)
{
bcmolt_xgpon_ni_state_change_completed * p_ind = (bcmolt_xgpon_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");
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_XGPON_NI_AUTO_CFG_ID_ONU_DISCOVERED == p_msg->subgroup)
{
bcmolt_xgpon_ni_onu_discovered *p_ind =
(bcmolt_xgpon_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 found ONU serial number "
"%c%c%c%c%d%d%d%d%d%d%d%d\n",
logical_pon,
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
);
/* if we got something from MAC HW, then it has to be PON interface */
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, BCM_ERR_OK,
BCMOLT_ACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID);
}
else
{
/* just get the pon key by typecasting to a dummy structure */
bcmolt_xgpon_ni_key *p_pon_key = &(((bcmolt_xgpon_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(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"Unhandled message indication for obj XGPON_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 xgpon (XG-PON1) 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_xgpon_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_xgpon_onu_key *p_xgpon_onu_key = &(((bcmolt_xgpon_onu_onu_activation_completed*)p_msg)->key);
do
{
if (BCMOLT_XGPON_ONU_AUTO_CFG_ID_ONU_ACTIVATION_COMPLETED == p_msg->subgroup)
{
bcmolt_xgpon_onu_onu_activation_completed *p_ind = (bcmolt_xgpon_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(logical_pon),
"sub_term %d (PON%d) activation 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_ADD,
p_msg->err, p_ind->data.status,
p_ind->data.fail_reason, BCMBAL_INVALID_TUNNEL_ID);
}
else if(BCMOLT_XGPON_ONU_AUTO_CFG_ID_ONU_DEACTIVATION_COMPLETED == p_msg->subgroup)
{
bcmolt_xgpon_onu_onu_deactivation_completed *p_ind = (bcmolt_xgpon_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,
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_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_xgpon_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_xgpon_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 XGPON_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_xgpon_onu_key->onu_id, maple_xgpon_mac_check_gem_port_id, maple_xgpon_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_xgpon_onu_key->onu_id, bcmos_strerror(rc));
break;
}
}while(0);
return rc;
}
/**
* @brief Handler function for Maple auto indications for xgpon (XG-PON1) 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_xgpon_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_XGPON_ALLOC_AUTO_CFG_ID_CONFIGURATION_COMPLETED == p_msg->subgroup)
{
bcmolt_xgpon_alloc_configuration_completed *p_ind = (bcmolt_xgpon_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_xgpon_alloc_key *p_pon_key = &(((bcmolt_xgpon_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 XGPON_ALLOC group %d "
"subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup);
}
}
while (0);
return rc;
}
/**
* @brief Maple auto indication register for specific xgpon (XG-PON1) 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_xgpon_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_xgpon_ind_handlers, BCM_SIZEOFARRAY(mac_util_xgpon_ind_handlers),device_id);
}
/**
* @brief common access terminal set for 10G pon if
*/
bcmos_errno mac_util_access_terminal_set_for_10G_itu_pon (bcmolt_device_cfg dev_cfg, bcmolt_devid device_id)
{
bcmos_errno rc;
bcmolt_device_nni_speed nni_speed_cfg;
#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
rc = bcmolt_cfg_set(device_id, &dev_cfg.hdr);
return rc;
}
/**
* @brief access terminal set for xgpon1_8
*/
bcmos_errno mac_util_access_terminal_set_for_xgpon_8 (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
{
bcmos_errno rc;
bcmolt_device_key key = {};
bcmolt_device_cfg dev_cfg;
rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
if (rc != BCM_ERR_OK)
return rc;
BCMOLT_CFG_INIT(&dev_cfg, device, key);
BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, BCMOLT_SYSTEM_MODE_XGPON_1__8_X);
rc = mac_util_access_terminal_set_for_10G_itu_pon(dev_cfg,device_id);
if (rc != BCM_ERR_OK)
return rc;
return maple_access_terminal_connect_common(device_id);
}
/**
* @brief access terminal set for xgs_2_10
*/
bcmos_errno mac_util_access_terminal_set_for_xgs (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id)
{
bcmos_errno rc;
bcmolt_device_key key = {};
bcmolt_device_cfg dev_cfg;
rc = maple_access_terminal_set_common(p_acc_term, op_type, device_id);
if (rc != BCM_ERR_OK)
return rc;
BCMOLT_CFG_INIT(&dev_cfg, device, key);
BCMOLT_CFG_PROP_SET(&dev_cfg, device, system_mode, BCMOLT_SYSTEM_MODE_XGS__2_X_10_G);
rc = mac_util_access_terminal_set_for_10G_itu_pon(dev_cfg, 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_xgpon_xgs(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_xgpon_ni_key ni_key = {};
bcmolt_xgpon_ni_cfg ni_cfg = {};
bcmolt_automatic_onu_deactivation automatic_onu_deactivation = {};
bcmolt_xgpon_sn_acquisition sn_acquisition_cfg = {};
bcmolt_xgpon_ni_auto_cfg xgpon_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, xgpon_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;
sn_acquisition_cfg.burst_profile = 0; /* Ranging burst profile - No FEC */
BCMOLT_CFG_PROP_SET(&ni_cfg, xgpon_ni, sn_acquisition, sn_acquisition_cfg);
/* Unlike GPON, the default behavior on Maple for XG-PON1 is not to deactivate the ONU in the below cases
* so here we specifically configure the Maple to behave on XG-PON1 as it does on GPON */
automatic_onu_deactivation.ack_timeout = BCMOS_TRUE;
automatic_onu_deactivation.loki = BCMOS_TRUE;
automatic_onu_deactivation.los = BCMOS_TRUE;
automatic_onu_deactivation.onu_alarms = BCMOS_TRUE;
automatic_onu_deactivation.sfi = BCMOS_TRUE;
automatic_onu_deactivation.tiwi = BCMOS_TRUE;
BCMOLT_CFG_PROP_SET(&ni_cfg, xgpon_ni, automatic_onu_deactivation, automatic_onu_deactivation);
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 and automatic onu deactivation configuration (%s),"
" device_id=%d, ni_key.pon_ni=%d, err_text=%s)\n",
bcmos_strerror(rc), device_id, ni_key.pon_ni, ni_cfg.hdr.hdr.err_text);
break;
}
/* turn off the auto indication messages for xgpon_ni.serial_number_acquisition_cycle_start */
BCMOLT_AUTO_CFG_INIT(&xgpon_ni_auto_cfg, xgpon_ni, ni_key);
BCMOLT_AUTO_CFG_PROP_SET(&xgpon_ni_auto_cfg, xgpon_ni, serial_number_acquisition_cycle_start, BCMOS_FALSE);
rc = bcmolt_auto_cfg_set(device_id, &xgpon_ni_auto_cfg.hdr);
if (rc != BCM_ERR_OK)
{
BCM_LOG(WARNING, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon),
"bcmolt_auto_cfg_set for xgpon_ni.serial_number_acquisition_cycle_start, Failed (%s), err_text=%s)\n",
bcmos_strerror(rc), xgpon_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 xgpon (XG-PON1)
*
* 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_xgpon(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;
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_xgpon_ni_set_pon_state oper_ni;
bcmolt_xgpon_ni_key ni_key = { .pon_ni = physical_if_id };
bcmolt_xgpon_trx_cfg cfg = {};
bcmolt_xgpon_trx_key trx_key = { .pon_ni = physical_if_id };
bcmolt_xgpon_trx_type trx_type;
if (BAL_UTIL_OPER_IF_UP == op_type)
{
/* set the pon_ni transceiver configuration */
BCMOLT_CFG_INIT(&cfg, xgpon_trx, trx_key);
/* Get the current default burst profiles */
rc = bcmolt_cfg_get(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 get trx configuration (%s), err_text=%s\n", bcmos_strerror(rc), cfg.hdr.hdr.err_text);
break;
}
/* 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))
{
if(BCM_TOPO_PON_MODE_XGPON == bcm_topo_pon_get_pon_mode(intf_key.intf_id))
{
/* The user didn't choose a transceiver type, so override it here
* with the default value for XGPON
*/
BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_XGPON);
}
else if (BCM_TOPO_PON_MODE_XGS == bcm_topo_pon_get_pon_mode(intf_key.intf_id))
{
/* The user didn't choose a transceiver type, so override it here
* with the default value for XGS
*/
BCMBAL_CFG_PROP_SET(p_interface_req, interface, transceiver_type, BCMBAL_MAC_UTIL_TRX_TYPE_DEFAULT_XGS);
}
}
/* Set the (default or chosen) transceiver configuration into the MAC device */
trx_type = mac_xgpon_bal_trx_type2bcm68620_trx_type(p_interface_req->data.transceiver_type);
BCMOLT_CFG_PROP_SET(&cfg, xgpon_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;
}
/* No need to Configure pon_ni Inter-working on XG-PON1 as
* direct mode is the only option available on this system mode
*/
}
/* invoke the pon_ni state change to the requested state */
BCMOLT_OPER_INIT(&oper_ni, xgpon_ni, set_pon_state, ni_key);
BCMOLT_OPER_PROP_SET(&oper_ni, xgpon_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 mac_util_validate_subscriber_terminal_info_for_xgpon (XG-PON1)
*
* 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_xgpon(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 xgpon 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, registration_id))
{
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id),
"Registration id is a mandatory parameter for a xgpon 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 xgpon (XG-PON1)
*
* 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_xgpon(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_xgpon_onu_cfg cfg = {};
bcmolt_xgpon_onu_cfg onu_cfg_get = {};
bcmolt_xgpon_onu_set_onu_state oper = {};
bcmolt_xgpon_onu_key key = {};
bcmolt_onu_operation new_onu_state;
/* 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, xgpon_onu, key);
/* invoke onu state change operation to the new state */
BCMOLT_OPER_INIT(&oper, xgpon_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, xgpon_onu, key);
BCMOLT_CFG_PROP_GET(&onu_cfg_get, xgpon_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 & Registration ID only if it being configured for the first time */
if (BCMOS_FALSE == is_post_discovery)
{
BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, serial_number,
*((bcmolt_serial_number *)&p_sub_term_req->data.serial_number));
BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, registration_id,
*((bcmolt_arr_u8_36 *)&p_sub_term_req->data.registration_id));
BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, registration_id_auto_learning, BCMOS_TRUE);
/* Ranging burst profile - No FEC */
BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, ranging_burst_profile, 0);
/* Data burst profile - No FEC */
BCMOLT_CFG_PROP_SET(&cfg, xgpon_onu, data_burst_profile, 1);
/* XG-PON1 - No need to set US FEC - it is part of the burst profile */
/* XG-PON1 - No need to set ONU management channel port as it is identical to the ONU 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;
}
/*
* 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(INFO, 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, xgpon_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 xgpon (XG-PON1)
*
* This routine is used to validate all input attributes required for a flow
* setting received from core for XG-PON1
*
* @param p_flow_req A pointer to a flow object
*
* @return bcmos_errno
*/
bcmos_errno mac_util_validate_flow_info_for_xgpon (const bcmbal_flow_cfg *p_flow_req)
{
bcmos_errno rc = BCM_ERR_OK;
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;
}
/* As there is no indication on gem port configuration completion, for xgpon
we will have to initiate querying it right after configuring it and retrieve the gem port state.
we can not assume it is activated (for example if the onu is not present)
*/
static bcmos_errno maple_mac_xgpon_update_svc_port_ind_flag (bcmbal_flow_cfg *p_flow_req, flow_list_entry *p_mac_util_flow_entry)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_xgpon_gem_port_key gem_key = {};
bcmolt_xgpon_gem_port_cfg gem_cfg = {};
bcmolt_devid device_id;
uint32_t physical_if_id;
GET_DEVICE_ID_AND_PHYSICAL_ID_FROM_IF_ID(p_flow_req->data.access_int_id, device_id, physical_if_id);
/* set the gem port object key */
gem_key.pon_ni = physical_if_id;
gem_key.gem_port_id = p_flow_req->data.svc_port_id;
BCMOLT_CFG_INIT(&gem_cfg, xgpon_gem_port, gem_key);
BCMOLT_CFG_PROP_GET(&gem_cfg, xgpon_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(p_flow_req->data.access_int_id),
"%s FAILED to gem xgpon_gem_port configuration : device_id = %d if_id = %d gem_port_id = %d \n",
__FUNCTION__,
device_id, p_flow_req->data.access_int_id, p_flow_req->data.svc_port_id);
return rc;
}
if ( BCMOLT_XGPON_GEM_PORT_STATE_ACTIVE == gem_cfg.data.gem_port_state)
{
p_mac_util_flow_entry->is_waiting_for_svc_port_active = BCMOS_FALSE;
}
return rc;
}
/**
* @brief flow set for xgpon (XG-PON1)
* @param p_flow_req pointer to flow request structure from core
* @param op_type ADD, REMOVE or CLEAR
* @param p_flow_core core FSM DB flow context passed as a cookie
*
* @return errno error
*
* @todo shift this out to mac specific files
*/
bcmos_errno mac_util_flow_set_for_xgpon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core)
{
bcmos_errno rc = BCM_ERR_OK;
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;
flow_list_entry *p_mac_util_flow_entry = NULL;
/* 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;
}
else
{
pbits_val = 0;
}
/* 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;
}
/* mark flow configuration to device completed */
mac_util_mark_flow_config_complete(p_mac_util_flow_entry);
rc = maple_mac_xgpon_update_svc_port_ind_flag (p_flow_req, 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);
}
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:
{
/** 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;
}
} /* Flow Remove */
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_xgpon_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_xgpon_gem_port_key gem_key = {};
bcmolt_xgpon_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, xgpon_gem_port, gem_key);
BCMOLT_CFG_PROP_GET(&gem_cfg, xgpon_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 to gem xgpon_gem_port configuration : device_id = %d if_id = %d gem_port_id = %d \n",
__FUNCTION__,
device_id, if_id, svc_port_id);
return rc;
}
/* may be configured; does gem belong to same onu ? */
if (BCMOLT_XGPON_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_XGPON_GEM_PORT_STATE_NOT_CONFIGURED != gem_cfg.data.gem_port_state;
*is_activated = BCMOLT_XGPON_GEM_PORT_STATE_ACTIVE == gem_cfg.data.gem_port_state;
return rc;
}
bcmos_errno maple_xgpon_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_xgpon_gem_port_key gem_key = {};
bcmolt_xgpon_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, xgpon_gem_port, gem_key);
/* set the gem port configuration */
if (onu_id < BCMOLT_XGPON_ONU_ID_ANY)
{
BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, onu_id, onu_id);
BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, upstream_destination_queue,
BCMOLT_US_GEM_PORT_DESTINATION_DATA);
}
BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, encryption_mode,
BCMOLT_CONTROL_STATE_DISABLE);
BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_gem_port, configuration, *configuration);
BCMOLT_CFG_PROP_SET(&gem_cfg, xgpon_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 if_id = %d onu_id = %d, err_text=%s\n",
__FUNCTION__,
bcmos_strerror(rc), rc, svc_port_id, if_id, onu_id, gem_cfg.hdr.hdr.err_text);
}
return rc;
}
bcmos_errno maple_xgpon_gem_port_id_remove(uint32_t if_id, uint16_t svc_port_id)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_xgpon_gem_port_key gem_key = {};
bcmolt_xgpon_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, xgpon_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 failed with error %s\n",__FUNCTION__, bcmos_strerror(rc));
}
return rc;
}
bcmos_errno maple_xgpon_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_xgpon_alloc_key alloc_key = {};
bcmolt_xgpon_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, xgpon_alloc, alloc_key);
BCMOLT_CFG_PROP_GET(&alloc_cfg, xgpon_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_xgpon_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_xgpon_alloc_key alloc_key = {};
bcmolt_xgpon_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, xgpon_alloc, alloc_key);
BCMOLT_CFG_PROP_SET(&alloc_cfg, xgpon_alloc, sla, agg_sla);
/* set the alloc-id - onu assignment */
BCMOLT_CFG_PROP_SET(&alloc_cfg, xgpon_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, sla = {g bw: %d, max bw: %d, cb_nrt_bw: %d, cb_rt_bw: %d}\n",
__FUNCTION__,
bcmos_strerror(rc), agg_id, if_id,
agg_sla.guaranteed_bw, agg_sla.maximum_bw, agg_sla.cbr_nrt_bw, agg_sla.cbr_rt_bw);
BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(if_id),
"err_text = %s\n",
alloc_cfg.hdr.hdr.err_text);
}
return rc;
}
bcmos_errno maple_xgpon_us_alloc_id_remove(uint32_t if_id, uint16_t agg_id)
{
bcmos_errno rc = BCM_ERR_OK;
bcmolt_xgpon_alloc_key alloc_key = {};
bcmolt_xgpon_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, xgpon_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 xgpon (XG-PON1)
* @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_xgpon (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 xgpon 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 may be 0 in the current info when the group had no owner.
skip the remove if that is the case */
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 xgpon 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_xgpon_gem_port_id_remove(if_id, svc_port_id);
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"mac_util xgpon 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 xgpon group operation SET on interface %d (gem %d) remove with 0 reference count \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_xgpon_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 xgpon group REM get reference count 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_xgpon_gem_port_id_remove(if_id, svc_port_id);
}
else if ( ref_count == 0)
{
BCM_LOG(WARNING, log_id_mac_util,
"mac_util xgpon group operation REM on interface %d (gem %d) remove with 0 reference count \n", if_id, svc_port_id);
}
}
if(BCM_ERR_OK != rc)
{
BCM_LOG(ERROR, log_id_mac_util,
"mac_util xgpon group set of operation %d on interface %d (gem %d) failed \n", op_type, if_id, svc_port_id);
break;
}
}
return rc;
}
/*@}*/