| /****************************************************************************** |
| * |
| * <: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_epon.c |
| * |
| * @brief mac util interfaces definition used by Bal Core for EPON |
| * |
| * 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_epon.h> |
| |
| #if BAL_EPON_EXCLUDE |
| #include <bcmolt_user_appl_epon_oam.h> |
| #include <bal_oam_util.h> |
| #include <bcmolt_eon.h> |
| |
| static bcmos_errno mac_util_indication_handle_for_epon_link (bcmolt_devid device_id, bcmolt_msg *p_msg); |
| static bcmos_errno mac_util_indication_handle_for_epon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg); |
| |
| |
| /** @brief array stores the list of EPON related auto indications from Maple to subscribe */ |
| static mac_util_ind_obj_and_handlers mac_util_epon_ind_handlers[] = |
| { |
| {BCMOLT_OBJ_ID_EPON_LINK, "BCMOLT_OBJ_ID_EPON_LINK", mac_util_indication_handle_for_epon_link}, |
| {BCMOLT_OBJ_ID_EPON_NI, "BCMOLT_OBJ_ID_EPON_NI", mac_util_indication_handle_for_epon_ni} |
| }; |
| |
| |
| /* epon onu entry structure */ |
| typedef enum |
| { |
| OAM_PROVISION_STATE_IDLE = 0, /**< idle - did not start yet */ |
| OAM_PROVISION_STATE_STARTED, /**< started - waiting to configure traffic cb to send bal core flow up indication */ |
| OAM_PROVISION_STATE_COMPLETED, /**< completed successfully */ |
| OAM_PROVISION_STATE_FAIL/**< failed to complete oam provision */ |
| } oam_provision_state; |
| |
| #define MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC 16 |
| typedef struct epon_onu_list_entry epon_onu_list_entry; |
| struct epon_onu_list_entry |
| { |
| TAILQ_ENTRY(epon_onu_list_entry) next; |
| bcmbal_subscriber_terminal_key bal_onu_key; /* bal onu key */ |
| bcmos_mac_address mac_address; |
| oam_provision_state oam_provision_state; |
| uint8_t waiting_flows_num; |
| bcmbal_flow_key flow_keys[MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC]; |
| uint32_t tunnel_id; |
| }; |
| |
| |
| static TAILQ_HEAD(epon_onu_list_head_t, epon_onu_list_entry) epon_onu_list; |
| |
| |
| /** @todo needs to be ported to the topology stub function */ |
| static bcmolt_devid maple_device_from_interface_get(uint16_t access_int_id) |
| { |
| /* For now, all interfaces map to device 0 */ |
| return (bcmolt_devid)0; |
| |
| } |
| |
| |
| static void epon_onu_list_add(epon_onu_list_entry *epon_onu_entry); |
| static epon_onu_list_entry *epon_onu_list_find_by_mac(const bcmos_mac_address *mac_address); |
| static epon_onu_list_entry *epon_onu_list_find_by_key(bcmbal_subscriber_terminal_key *key); |
| static void epon_onu_list_remove_by_key(bcmbal_subscriber_terminal_key *key); |
| |
| static void mac_util_configure_traffic_cb(void *context, |
| bcmolt_devid device_id, |
| bcmolt_epon_ni epon_ni, |
| const bcmos_mac_address *mac_address, |
| bcmos_errno result); |
| |
| static void mac_util_unconfigure_traffic_cb(void *context, |
| bcmolt_devid device_id, |
| bcmolt_epon_ni epon_ni, |
| const bcmos_mac_address *mac_address, |
| bcmos_errno result); |
| |
| |
| #define _mac_addr_fmt_str "<%02x:%02x:%02x:%02x:%02x:%02x>" |
| #define _mac_addr_data(mac) \ |
| (mac).u8[0], \ |
| (mac).u8[1], \ |
| (mac).u8[2], \ |
| (mac).u8[3], \ |
| (mac).u8[4], \ |
| (mac).u8[5] |
| |
| |
| static void mac_util_oam_negotiation_cb(void *context, bcmolt_devid device_id, bcmolt_epon_ni epon_ni, const bcmos_mac_address *mac_address, bcmos_errno result) |
| { |
| |
| epon_onu_list_entry *p_onu_entry = context; |
| uint32_t logical_pon; |
| bcmos_errno rc; |
| |
| do |
| { |
| |
| rc = bcm_topo_pon_get_physical2logical(device_id, epon_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, epon_ni, bcmos_strerror(rc)); |
| break; |
| } |
| |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), |
| "device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n", |
| device_id, epon_ni, _mac_addr_data(*mac_address), result == BCM_ERR_OK ? "success" : "fail"); |
| |
| |
| mac_util_report_sub_term_event(logical_pon, |
| p_onu_entry->bal_onu_key.sub_term_id, |
| (bcmolt_serial_number *)NULL, |
| BAL_UTIL_OPER_SUB_TERM_ADD, |
| result, |
| result == BCM_ERR_OK ? BCMOLT_RESULT_SUCCESS : BCMOLT_RESULT_FAIL, |
| BCMOLT_ACTIVATION_FAIL_REASON_NONE, |
| result == BCM_ERR_OK ? p_onu_entry->tunnel_id : BCMBAL_INVALID_TUNNEL_ID); |
| |
| } |
| while(0); |
| |
| } |
| |
| /** |
| * @brief get string for the indication object type for epon |
| */ |
| static char *mac_util_indication_get_obj_type_str_for_epon (bcmolt_obj_id obj_type) |
| { |
| return _mac_util_get_obj_type_str_for_indications (obj_type, mac_util_epon_ind_handlers, BCM_SIZEOFARRAY(mac_util_epon_ind_handlers)); |
| } |
| |
| /** |
| * @brief all the maple indication handlers for epon |
| * |
| * @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_epon (bcmolt_devid device_id, bcmolt_msg *p_msg) |
| { |
| int i = 0; |
| |
| 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_for_epon(p_msg->obj_type), |
| p_msg->group, p_msg->subgroup); |
| |
| for (i=0; i < BCM_SIZEOFARRAY(mac_util_epon_ind_handlers); i++) |
| { |
| if (p_msg->obj_type == mac_util_epon_ind_handlers[i].obj_type) |
| { |
| return mac_util_epon_ind_handlers[i].ind_handler (device_id, p_msg); |
| } |
| } |
| |
| /* log an error if unhandled */ |
| return BCM_ERR_INTERNAL; |
| } |
| |
| |
| /** |
| * @brief Handler function for Maple auto indications for EPON Link |
| * |
| * @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_epon_link (bcmolt_devid device_id, bcmolt_msg *p_msg) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| uint32_t logical_pon; |
| |
| do |
| { |
| if (BCMOLT_EPON_LINK_AUTO_ID_MPCP_DISCOVERED == p_msg->subgroup) |
| { |
| epon_onu_list_entry *p_onu_entry; |
| bcmolt_epon_link_mpcp_discovered * p_ind = (bcmolt_epon_link_mpcp_discovered*)p_msg; |
| |
| rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.epon_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.epon_ni, bcmos_strerror(rc)); |
| break; |
| } |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), |
| "llid indication received obj=%d group=%d subgroup=%d err=%d; " |
| "link_status = %s (%d), llid = (0x%04x) tunnel_id = (0x%08x)\n", |
| p_msg->obj_type, p_msg->group, p_msg->subgroup, p_msg->err, |
| p_ind->data.link_info.link_status==BCMOLT_EPON_LINK_STATUS_DISCOVERED ? "Discovered" : "other", |
| p_ind->data.link_info.link_status, |
| p_ind->data.link_info.llid, |
| p_ind->data.link_info.tunnel_id); |
| |
| |
| |
| if(NULL == (p_onu_entry = epon_onu_list_find_by_mac(&(p_ind->key.mac_address)))) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), |
| "Failed to find epon onu related to received frame captured\n"); |
| rc = BCM_ERR_INTERNAL; |
| } |
| else |
| { |
| |
| p_onu_entry->tunnel_id = p_ind->data.link_info.tunnel_id; |
| bal_oam_start_oam_negotiation(device_id, |
| p_ind->key.epon_ni, |
| &p_ind->key.mac_address, |
| mac_util_oam_negotiation_cb, |
| p_onu_entry); |
| } |
| } |
| } |
| while(0); |
| |
| return rc; |
| } |
| |
| |
| /** |
| * @brief Handler function for Maple auto indications for EPON 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_epon_ni (bcmolt_devid device_id, bcmolt_msg *p_msg) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| uint32_t logical_pon; |
| do |
| { |
| |
| if (BCMOLT_EPON_NI_AUTO_ID_STATE_CHANGE_COMPLETED == p_msg->subgroup) |
| { |
| bcmolt_epon_ni_state_change_completed * p_ind = (bcmolt_epon_ni_state_change_completed *)p_msg; |
| rc = bcm_topo_pon_get_physical2logical(device_id, p_ind->key.epon_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.epon_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_EPON_NI_EN_STATE_ENABLED == p_ind->data.new_state ? "up" : "down"); |
| |
| mac_util_report_if_event(logical_pon, BCMBAL_INTF_TYPE_PON, p_msg->err, |
| BCMOLT_RESULT_SUCCESS, p_ind->data.new_state); |
| } |
| else |
| { |
| /* just get the pon key by typecasting to a dummy structure */ |
| bcmolt_epon_ni_key *p_pon_key = &(((bcmolt_epon_ni_state_change_completed*)p_msg)->key); |
| |
| rc = bcm_topo_pon_get_physical2logical(device_id, p_pon_key->epon_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->epon_ni, bcmos_strerror(rc)); |
| break; |
| } |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(logical_pon), |
| "Unhandled message indication for obj Epon_NI group %d " |
| "subgroup %d (Ignored)\n", p_msg->group, p_msg->subgroup); |
| } |
| |
| |
| |
| } |
| while(0); |
| return rc; |
| } |
| |
| |
| /** |
| * @brief Maple auto indication register for specific EPON 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_epon_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_epon_ind_handlers, BCM_SIZEOFARRAY(mac_util_epon_ind_handlers), device_id); |
| } |
| #endif /* BAL_EPON_EXCLUDE */ |
| |
| static bcmos_errno mac_util_epon_access_terminal_set( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id, |
| bcmolt_system_mode system_mode, |
| bcmolt_nni_speed nni_speed) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmolt_device_key key = {}; |
| bcmolt_device_nni_speed nni_speed_cfg; |
| 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, system_mode); |
| |
| nni_speed_cfg.first_half = nni_speed; |
| nni_speed_cfg.second_half = nni_speed; |
| BCMOLT_CFG_PROP_SET(&dev_cfg, device, nni_speed, nni_speed_cfg); |
| |
| /** @todo with multiple devices the mechanism to configure acces term will change */ |
| rc = bcmolt_cfg_set(device_id, &dev_cfg.hdr); |
| if (rc != BCM_ERR_OK) |
| return rc; |
| |
| return maple_access_terminal_connect_common(device_id); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_8_tdma( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA, |
| BCMOLT_NNI_SPEED_GBPS_12P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_4_tdma( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA, |
| BCMOLT_NNI_SPEED_GBPS_12P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_16_1g( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__16_X, |
| BCMOLT_NNI_SPEED_GBPS_2P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_8_1g( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__8_X, |
| BCMOLT_NNI_SPEED_GBPS_2P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_4_1g( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__4_X, |
| BCMOLT_NNI_SPEED_GBPS_2P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_8_10g( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__8_X_10_G, |
| BCMOLT_NNI_SPEED_GBPS_12P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_4_10g( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__4_X_10_G, |
| BCMOLT_NNI_SPEED_GBPS_12P5); |
| } |
| |
| bcmos_errno mac_util_access_terminal_set_for_epon_2_10g( |
| acc_term_inst *p_acc_term, |
| bal_util_oper_acc_term op_type, |
| bcmolt_devid device_id) |
| { |
| return mac_util_epon_access_terminal_set( |
| p_acc_term, |
| op_type, |
| device_id, |
| BCMOLT_SYSTEM_MODE_EPON__2_X_10_G, |
| BCMOLT_NNI_SPEED_GBPS_12P5); |
| } |
| |
| /** |
| * @brief Command Set setup routine for interface up to mac application for EPON |
| * |
| * 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_epon(acc_term_interface *p_interface_inst, bal_util_oper_if op_type) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key; |
| 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)); |
| return rc; |
| } |
| |
| bcmolt_epon_ni_key key; |
| bcmolt_epon_ni_cfg cfg; |
| bcmolt_epon_ni_set_epon_ni_en_state oper; |
| |
| key.epon_ni = physical_if_id; |
| |
| BCMOLT_CFG_INIT(&cfg, epon_ni, key); |
| |
| if (BAL_UTIL_OPER_IF_UP == op_type) |
| { |
| BCMOLT_CFG_PROP_SET(&cfg, epon_ni, registration_behavior, BCMOLT_REGISTRATION_BEHAVIOR_NOTIFY_UNKNOWN); |
| |
| 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 %s (set) pon interface (%d) - %s, err_text=%s\n", |
| (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate", |
| rc, bcmos_strerror(rc), cfg.hdr.hdr.err_text); |
| return rc; |
| } |
| } |
| |
| BCMOLT_OPER_INIT(&oper, epon_ni, set_epon_ni_en_state, key); |
| BCMOLT_OPER_PROP_SET(&oper, epon_ni, set_epon_ni_en_state, new_state, |
| (BAL_UTIL_OPER_IF_UP == op_type ? |
| BCMOLT_EPON_NI_EN_STATE_ENABLED : BCMOLT_EPON_NI_EN_STATE_DISABLED)); |
| |
| rc = bcmolt_oper_submit(device_id, &oper.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 (%d) - %s, err_text=%s\n", |
| (BAL_UTIL_OPER_IF_UP == op_type) ? "activate" : "deactivate", |
| rc, bcmos_strerror(rc), oper.hdr.hdr.err_text); |
| } |
| else |
| { |
| 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; |
| } |
| /*---------------------------------------------------------------------------------------------*/ |
| |
| |
| |
| |
| |
| #if BAL_EPON_EXCLUDE |
| /** |
| * @brief mac_util_validate_subscriber_terminal_info_for_epon |
| * |
| * This routine is used to validate all input attributes required for a sub term setting |
| * received from core for EPON |
| * |
| * @param p_sub_term_req A pointer to a subscriber terminal object |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_validate_subscriber_terminal_info_for_epon(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, mac_address)) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id), |
| "mac_address is a mandatory parameter for an epon 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 EPON |
| * |
| * 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 This parameter is ignored for epon |
| * |
| * @return bcmos_errno |
| */ |
| bcmos_errno mac_util_subscriber_terminal_set_for_epon(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; |
| |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id), |
| "IN : %s pon_id = %d onu_id= %d " |
| "omci_gem_port = %d\n", |
| __FUNCTION__, |
| p_sub_term_req->key.intf_id, |
| p_sub_term_req->key.sub_term_id, p_sub_term_req->data.svc_port_id); |
| |
| if ((BAL_UTIL_OPER_SUB_TERM_ADD != op_type) |
| && (BAL_UTIL_OPER_SUB_TERM_REMOVE != op_type) |
| && (BAL_UTIL_OPER_SUB_TERM_CLEAR != op_type)) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id), |
| "Unsupported operation %d for sub_term %u\n", |
| op_type, p_sub_term_req->key.sub_term_id); |
| return BCM_ERR_NOT_SUPPORTED; |
| } |
| |
| 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; |
| } |
| |
| epon_onu_list_entry * p_new_epon_onu_entry; |
| bcmolt_epon_ni_key key; |
| bcmolt_epon_ni_add_link oper; |
| |
| key.epon_ni = physical_if_id; |
| BCMOLT_OPER_INIT(&oper, epon_ni, add_link, key); |
| |
| if(BAL_UTIL_OPER_SUB_TERM_ADD == op_type) |
| { |
| |
| BCMOLT_OPER_PROP_SET(&oper, epon_ni, add_link, mac_address, p_sub_term_req->data.mac_address); |
| BCMOLT_OPER_PROP_SET(&oper, epon_ni, add_link, rate, BCMOLT_EPON_LINK_RATE_TEN_TEN); |
| rc = bcmolt_oper_submit(device_id, &oper.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 register epon onu epon_ni = %d mac : "_mac_addr_fmt_str" rc = %d (%s), err_text=%s\n", |
| key.epon_ni, _mac_addr_data(p_sub_term_req->data.mac_address), rc, bcmos_strerror(rc), |
| oper.hdr.hdr.err_text); |
| break; |
| } |
| /* add the new epon onu to the epon onu list to follow indications and oam sending */ |
| p_new_epon_onu_entry = bcmos_calloc(sizeof(epon_onu_list_entry)); |
| if (NULL == p_new_epon_onu_entry) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id), |
| "Failed to allocate the epon onu entry\n"); |
| rc = BCM_ERR_NOMEM; |
| break; |
| } |
| |
| memcpy(&p_new_epon_onu_entry->bal_onu_key, &p_sub_term_req->key, |
| sizeof(bcmbal_subscriber_terminal_key)); |
| p_new_epon_onu_entry->mac_address = p_sub_term_req->data.mac_address; |
| p_new_epon_onu_entry->oam_provision_state = OAM_PROVISION_STATE_IDLE; |
| p_new_epon_onu_entry->waiting_flows_num = 0; |
| |
| epon_onu_list_add(p_new_epon_onu_entry); |
| } |
| else |
| { |
| 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, |
| BCM_ERR_OK, BCMOLT_RESULT_SUCCESS, |
| MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE, BCMBAL_INVALID_TUNNEL_ID); |
| |
| epon_onu_list_remove_by_key(&p_sub_term_req->key); |
| |
| } |
| } while (0); |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_sub_term_req->key.intf_id), |
| "OUT : going out of %s rc = %s (%d)\n", |
| __FUNCTION__, |
| bcmos_strerror(rc), rc); |
| |
| |
| return rc; |
| } |
| |
| |
| |
| |
| |
| static bcmos_errno maple_us_sla_configure_epon(bcmbal_flow_cfg *flow_entry, bcmos_mac_address *mac) |
| { |
| bcmolt_epon_link_key epon_link_key; |
| bcmolt_epon_link_cfg epon_link_cfg; |
| bcmolt_upstream_bandwidth_distribution us_bw_dist = {}; |
| |
| bcmolt_devid device_id; |
| uint32_t physical_if_id; |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| /* get physical interface from logical interface */ |
| rc = bcm_topo_pon_get_logical2physical (flow_entry->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(flow_entry->data.access_int_id), |
| "Failed to get physical if from logical if (%s)\n", bcmos_strerror(rc)); |
| } |
| else |
| { |
| |
| epon_link_key.epon_ni = physical_if_id; |
| epon_link_key.mac_address = *mac; |
| BCMOLT_CFG_INIT(&epon_link_cfg, epon_link, epon_link_key); |
| |
| us_bw_dist.polling_interval_us = BCMOLT_POLLING_INTERVAL_AUTOMATIC; |
| if (BCMBAL_ATTRIBUTE_PROP_IS_SET(&flow_entry->data.sla, sla, min_rate)) |
| { |
| us_bw_dist.min_schedulershaper.bandwidth_Kbps = flow_entry->data.sla.min_rate; |
| } |
| if (BCMBAL_ATTRIBUTE_PROP_IS_SET(&flow_entry->data.sla, sla, max_rate)) |
| { |
| us_bw_dist.max_schedulershaper.bandwidth_Kbps = flow_entry->data.sla.max_rate; |
| } |
| else |
| { |
| us_bw_dist.max_schedulershaper.bandwidth_Kbps = 10000000; |
| } |
| us_bw_dist.max_schedulershaper.priority = 7; |
| |
| BCMOLT_CFG_PROP_SET(&epon_link_cfg, epon_link, upstream_bandwidth, us_bw_dist); |
| return bcmolt_cfg_set(device_id, &epon_link_cfg.hdr); |
| } |
| |
| return rc; |
| } |
| |
| |
| |
| |
| |
| |
| /** |
| * @brief flow set for EPON |
| * |
| * @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_epon (bcmbal_flow_cfg *p_flow_req, bal_util_oper_flow op_type, flow_inst *p_flow_core) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| epon_onu_list_entry *p_onu_entry; |
| bcmos_mac_address mac; |
| bcmbal_subscriber_terminal_key key; |
| |
| |
| key.intf_id = p_flow_req->data.access_int_id; |
| key.sub_term_id = p_flow_req->data.sub_term_id; |
| |
| if(NULL != (p_onu_entry = epon_onu_list_find_by_key(&key))) |
| { |
| mac = p_onu_entry->mac_address; |
| } |
| else |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "failed to configure flow, " |
| "subscriber terminal if=%d sub-term id = %d was not found - no such device\n", |
| p_flow_req->data.access_int_id, p_flow_req->data.sub_term_id); |
| |
| return BCM_ERR_NOENT; |
| } |
| |
| |
| |
| if (BAL_UTIL_OPER_FLOW_ADD == op_type) |
| { |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), "add, context is %p\n", p_flow_context); |
| |
| switch (p_onu_entry->oam_provision_state) |
| { |
| case OAM_PROVISION_STATE_IDLE: |
| { |
| p_onu_entry->flow_keys[p_onu_entry->waiting_flows_num++] = p_flow_req->key; |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "add p_onu_entry-> %p, waiting flows: %d context is %p\n", |
| p_onu_entry, p_onu_entry->waiting_flows_num, p_flow_context); |
| |
| rc = maple_us_sla_configure_epon(p_flow_req, &mac); |
| if (rc != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "Unable to configure EPON US SLA (%s)\n", bcmos_strerror(rc)); |
| |
| break; |
| } |
| |
| p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_STARTED; |
| |
| bal_oam_configure_traffic(maple_device_from_interface_get(p_flow_req->data.access_int_id), |
| p_flow_req->data.access_int_id, |
| &mac, |
| BCMOS_TRUE, |
| mac_util_configure_traffic_cb, p_flow_context); |
| } |
| break; |
| |
| |
| case OAM_PROVISION_STATE_STARTED: |
| { |
| if (p_onu_entry->waiting_flows_num < MAC_UTIL_MAX_WAITING_FLOWS_PER_MAC) |
| { |
| p_onu_entry->flow_keys[p_onu_entry->waiting_flows_num++] = p_flow_req->key; |
| } |
| else |
| { |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "failed to configure flow for that mac, " |
| "too many flows already waiting for oam configuration\n"); |
| rc = BCM_ERR_INSUFFICIENT_LIST_MEM; |
| } |
| } |
| break; |
| |
| |
| case OAM_PROVISION_STATE_COMPLETED: |
| { |
| mac_util_report_flow_add_success(p_flow_req->key, p_flow_req->data.access_int_id); |
| } |
| break; |
| |
| |
| case OAM_PROVISION_STATE_FAIL: |
| default: |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "failed to configure oam traffic for that mac,\n"); /* currently no failure indications */ |
| } |
| break; |
| } |
| } |
| else /* REMOVE or CLEAR FLOW */ |
| { |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "delete p_onu_entry-> %p, waiting flows: %d, provisioned state is %d, context is %p\n", |
| p_onu_entry, |
| p_onu_entry->waiting_flows_num, |
| p_onu_entry->oam_provision_state, |
| p_flow_context); |
| |
| switch (p_onu_entry->oam_provision_state) |
| { |
| case OAM_PROVISION_STATE_IDLE: |
| { |
| mac_util_report_flow_remove_success(p_flow_req->key, p_flow_req->data.access_int_id, op_type); |
| } |
| break; |
| |
| case OAM_PROVISION_STATE_COMPLETED: |
| { |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "calling bal_oam_configure_traffic w/ \"Disable\" state\n"); |
| |
| bal_oam_configure_traffic(maple_device_from_interface_get(p_flow_req->data.access_int_id), |
| p_flow_req->data.access_int_id, |
| &mac, |
| BCMOS_FALSE, |
| mac_util_unconfigure_traffic_cb, |
| p_flow_context); |
| } |
| break; |
| |
| case OAM_PROVISION_STATE_FAIL: |
| case OAM_PROVISION_STATE_STARTED: |
| default: |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(key.intf_id), |
| "failed to unconfigure oam traffic for that mac,\n"); /* currently no failure indications */ |
| } |
| break; |
| } |
| } |
| |
| return rc; |
| } |
| |
| static void mac_util_configure_traffic_cb(void *context, |
| bcmolt_devid device_id, |
| bcmolt_epon_ni epon_ni, |
| const bcmos_mac_address *mac_address, |
| bcmos_errno result) |
| { |
| epon_onu_list_entry *p_onu_entry; |
| int i; |
| |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), |
| "configure device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n", |
| device_id, epon_ni, _mac_addr_data(*mac_address), result == BCM_ERR_OK ? "success" : "fail"); |
| |
| |
| if(NULL == (p_onu_entry = epon_onu_list_find_by_mac(mac_address))) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), |
| "FAIL - received configure traffic cb for mac that was not configured " _mac_addr_fmt_str "\n", |
| _mac_addr_data(*mac_address)); |
| return; |
| } |
| |
| if (OAM_PROVISION_STATE_STARTED != p_onu_entry->oam_provision_state) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), |
| "FAIL - received configure traffic cb for mac that is in the wrong state (%d)\n", |
| p_onu_entry->oam_provision_state); |
| return; |
| } |
| |
| if (result == BCM_ERR_OK) |
| { |
| p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_COMPLETED; |
| |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), "Moved ONU to OAM COMPLETED state\n"); |
| |
| for (i=0; i<p_onu_entry->waiting_flows_num; i++) |
| { |
| mac_util_report_flow_add_success(p_onu_entry->flow_keys[i], epon_ni); |
| } |
| } |
| else |
| { |
| p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_FAIL; |
| } |
| |
| p_onu_entry->waiting_flows_num = 0; /* currently we dont send fail indication */ |
| } |
| |
| /** EPON specific traffic unconfigure; Not used for GPON mode */ |
| static void mac_util_unconfigure_traffic_cb(void *context, |
| bcmolt_devid device_id, |
| bcmolt_epon_ni epon_ni, |
| const bcmos_mac_address *mac_address, |
| bcmos_errno result) |
| { |
| flow_inst *p_flow_core = (flow_inst *)(context); |
| epon_onu_list_entry *p_onu_entry; |
| |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(epon_ni), |
| "unconfigure device_id=%u, epon_ni=%u, mac_address=" _mac_addr_fmt_str " result='%s'\n", |
| device_id, |
| epon_ni, |
| _mac_addr_data(*mac_address), |
| result == BCM_ERR_OK ? "success" : "fail"); |
| |
| |
| /** @todo need to pass on the actual op type (REMOVE or CLEAR) */ |
| mac_util_report_flow_remove_success(p_flow_core->current_flow_info.key, epon_ni, BAL_UTIL_OPER_FLOW_REMOVE); |
| |
| if(NULL != (p_onu_entry = epon_onu_list_find_by_mac(mac_address))) |
| { |
| p_onu_entry->oam_provision_state = OAM_PROVISION_STATE_IDLE; |
| } |
| } |
| |
| |
| |
| /** |
| * @brief used for epon oam message handling |
| * |
| * @param device_id bcm dev id |
| * @param p_msg oam msg pointer |
| */ |
| void bal_proxy_rx_cb_for_epon (bcmolt_devid device_id, bcmolt_msg *p_msg) |
| { |
| bcmolt_proxy_rx *proxy_rx = (bcmolt_proxy_rx *)p_msg; |
| |
| bcmolt_user_appl_eon_process_rx(device_id, proxy_rx); |
| bcmolt_user_appl_epon_oam_handle_rx(device_id, proxy_rx, bal_oam_proxy_rx_cb); |
| |
| /** @note the free of p_msg is done in caller function */ |
| } |
| |
| |
| /** |
| * @brief init for epon oam and eon |
| * |
| */ |
| static void mac_util_init_oam_for_epon (void) |
| { |
| bcmolt_user_appl_epon_oam_init(); |
| bcmolt_user_appl_eon_init(); |
| } |
| |
| |
| |
| |
| static void epon_onu_list_add(epon_onu_list_entry *epon_onu_entry) |
| { |
| TAILQ_INSERT_HEAD(&epon_onu_list, epon_onu_entry, next); |
| return; |
| } |
| |
| static void epon_onu_list_remove_by_key(bcmbal_subscriber_terminal_key *key) |
| { |
| epon_onu_list_entry *p_onu_entry = NULL; |
| |
| if(NULL != (p_onu_entry = epon_onu_list_find_by_key(key))) |
| { |
| TAILQ_REMOVE(&epon_onu_list, p_onu_entry, next); |
| bcmos_free(p_onu_entry); |
| } |
| |
| return; |
| } |
| |
| static epon_onu_list_entry *epon_onu_list_find_by_mac(const bcmos_mac_address *mac_address) |
| { |
| epon_onu_list_entry *p_onu_entry = NULL; |
| epon_onu_list_entry *current_onu_entry; |
| |
| TAILQ_FOREACH(current_onu_entry, &epon_onu_list, next) |
| { |
| if (memcmp(¤t_onu_entry->mac_address, mac_address, sizeof(bcmos_mac_address))==0) |
| { |
| p_onu_entry = current_onu_entry; |
| break; |
| } |
| } |
| |
| return p_onu_entry; |
| } |
| |
| static epon_onu_list_entry *epon_onu_list_find_by_key(bcmbal_subscriber_terminal_key *key) |
| { |
| epon_onu_list_entry *p_onu_entry = NULL; |
| epon_onu_list_entry *current_onu_entry; |
| |
| TAILQ_FOREACH(current_onu_entry, &epon_onu_list, next) |
| { |
| if ((current_onu_entry->bal_onu_key.intf_id == key->intf_id) && |
| (current_onu_entry->bal_onu_key.sub_term_id == key->sub_term_id)) |
| { |
| p_onu_entry = current_onu_entry; |
| break; |
| } |
| } |
| |
| return p_onu_entry; |
| } |
| #endif /* BAL_EPON_EXCLUDE */ |
| |
| /*@}*/ |