| /****************************************************************************** |
| * |
| * <: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.c |
| * |
| * @brief mac util interfaces definition used by Bal Core |
| * |
| * 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> |
| #include <bal_mac_util_epon.h> |
| |
| #include <bal_worker.h> |
| #include <bal_core.h> |
| #include <bal_cli.h> |
| |
| #ifdef BOARD |
| #include <bcmolt_board.h> |
| #include <bcmolt_board_cli.h> |
| #endif |
| #include <bcm_api_cli.h> |
| #include <bcmolt_dev_selector.h> |
| #include <bcmolt_host_sw_version.h> |
| #include <bcmolt_model_revision.h> |
| |
| #ifdef ENABLE_LOG |
| |
| #define INBOLD_BAD(a) "\033[31m"a"\033[0m" |
| /* |
| * mac util logging for generic logging, as well as on per PON basis |
| */ |
| dev_log_id log_id_mac_util; |
| dev_log_id log_id_mac_util_pon_if[NUM_SUPPORTED_SUBSCRIBER_INTERFACES]; |
| |
| /** @def size of log Id string */ |
| #define MAC_UTIL_LOG_STR_SZ 64 |
| |
| /** @def to make a log string for a PON interface, to register with logging module during initialization */ |
| #define MAC_UTIL_MAKE_LOG_STR_FOR_PON_IF(_pon_if_id, _buf, _buf_sz) \ |
| do \ |
| { \ |
| int n = 0; \ |
| n = snprintf((_buf), (_buf_sz), "MAC_UTIL_PON_%d", (_pon_if_id)); \ |
| BUG_ON((0 > n) || ((_buf_sz) <= n)); \ |
| } while (0); \ |
| |
| static bcmos_errno mac_util_register_logging_per_pon (void); |
| #endif //ENABLE_LOG |
| |
| /* This is not exposed in the object model, so we can use BCMOLT_SYSTEM_MODE__NUM_OF as a special value for loopback. */ |
| #define BCMOLT_SYSTEM_MODE_LOOPBACK BCMOLT_SYSTEM_MODE__NUM_OF |
| #define BCM_TOPO_PON_MODE_LOOPBACK BCM_TOPO_PON_MODE__NUM_OF |
| |
| static bcmos_errno mac_util_indication_handle_for_device (bcmolt_devid device_id, bcmolt_msg *p_msg); |
| static bcmos_errno mac_util_system_mode_get(bcmolt_devid device_id); |
| |
| /* Maple CLI directory */ |
| static bcmcli_entry *maple_dir; |
| |
| /** @brief array stores the list of device related auto indications from Maple to subscribe */ |
| static mac_util_ind_obj_and_handlers mac_util_device_ind_handlers[] = |
| { |
| {BCMOLT_OBJ_ID_DEVICE, "BCMOLT_OBJ_ID_DEVICE", mac_util_indication_handle_for_device} |
| }; |
| |
| |
| |
| #if !defined(WRX_BUILD) |
| /* external structures to be used with bcmos_tr |
| * specifying IP:Port assignments of the remote mac device */ |
| extern uint32_t bcmtr_olt_ip[BCMTR_MAX_OLTS]; |
| extern uint16_t bcmtr_olt_udp_port[BCMTR_MAX_OLTS]; |
| extern uint16_t bcmtr_host_udp_port; |
| #endif |
| |
| |
| |
| /** |
| * @brief BAL request handlers for system mode specific set & validate |
| **/ |
| static mac_util_bal_req_handlers_for_system_mode_t mac_util_bal_req_handlers_for_system_mode[] = |
| { |
| [BCMOLT_SYSTEM_MODE_GPON__16_X] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_gpon_16, |
| .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_gpon |
| }, |
| [BCMOLT_SYSTEM_MODE_GPON__8_X] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_gpon_8, |
| .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_gpon |
| }, |
| [BCMOLT_SYSTEM_MODE_XGPON_1__8_X] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_xgpon_8, |
| .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_xgpon_xgs |
| }, |
| [BCMOLT_SYSTEM_MODE_XGS__2_X_10_G] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_xgs, |
| .acc_term_post_indication_set = mac_util_access_terminal_post_indication_set_for_xgpon_xgs |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_8_tdma, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_4_tdma, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__16_X] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_16_1g, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__8_X] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_8_1g, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__4_X] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_4_1g, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__8_X_10_G] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_8_10g, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__4_X_10_G] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_4_10g, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_EPON__2_X_10_G] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_epon_2_10g, |
| .acc_term_post_indication_set = NULL |
| }, |
| [BCMOLT_SYSTEM_MODE_LOOPBACK] = |
| { |
| .acc_term_set = mac_util_access_terminal_set_for_loopback, |
| .acc_term_post_indication_set = NULL |
| } |
| }; |
| |
| /** |
| * @brief BAL request handlers for PON protocol specific set & validate |
| * |
| * @note The handling would be like object-oriented programming. The common |
| * handling would be done in the top level call. And then based on protocol, |
| * the mac specific handling will be done in the corresponding mac specific |
| * handler functions. |
| **/ |
| mac_util_handlers_per_pon_mode_t mac_util_bal_req_handlers_for_pon_mode [BCM_TOPO_PON_MODE__NUM_OF + 1] = |
| { |
| [BCM_TOPO_PON_MODE_GPON] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_gpon, |
| .sub_term_validate = mac_util_validate_subscriber_terminal_info_for_gpon, |
| .sub_term_set = mac_util_subscriber_terminal_set_for_gpon, |
| .flow_validate = mac_util_validate_flow_info_for_gpon, |
| .flow_set = mac_util_flow_set_for_gpon, |
| .group_validate = NULL, |
| .group_set = mac_util_group_set_for_gpon, |
| .sla_us_rate_factor = 1 |
| }, |
| [BCM_TOPO_PON_MODE_XGPON] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_xgpon, |
| .sub_term_validate = mac_util_validate_subscriber_terminal_info_for_xgpon, |
| .sub_term_set = mac_util_subscriber_terminal_set_for_xgpon, |
| .flow_validate = mac_util_validate_flow_info_for_xgpon, |
| .flow_set = mac_util_flow_set_for_xgpon, |
| .group_validate = NULL, |
| .group_set = mac_util_group_set_for_xgpon, |
| .sla_us_rate_factor = 2 |
| }, |
| [BCM_TOPO_PON_MODE_XGS] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_xgpon, |
| .sub_term_validate = mac_util_validate_subscriber_terminal_info_for_xgpon, |
| .sub_term_set = mac_util_subscriber_terminal_set_for_xgpon, |
| .flow_validate = mac_util_validate_flow_info_for_xgpon, |
| .flow_set = mac_util_flow_set_for_xgpon, |
| .group_validate = NULL, |
| .group_set = mac_util_group_set_for_xgpon, |
| .sla_us_rate_factor = 8 |
| }, |
| [BCM_TOPO_PON_MODE_EPON_TDMA] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_epon, |
| .sub_term_validate = NULL, |
| .sub_term_set = NULL, |
| .flow_validate = NULL, |
| .flow_set = NULL, |
| .group_validate = NULL, |
| .group_set = NULL, |
| .sla_us_rate_factor = 0 |
| }, |
| [BCM_TOPO_PON_MODE_EPON_1G] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_epon, |
| .sub_term_validate = NULL, |
| .sub_term_set = NULL, |
| .flow_validate = NULL, |
| .flow_set = NULL, |
| .group_validate = NULL, |
| .group_set = NULL, |
| .sla_us_rate_factor = 0 |
| }, |
| [BCM_TOPO_PON_MODE_EPON_10G] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_epon, |
| .sub_term_validate = NULL, |
| .sub_term_set = NULL, |
| .flow_validate = NULL, |
| .flow_set = NULL, |
| .group_validate = NULL, |
| .group_set = NULL, |
| .sla_us_rate_factor = 0 |
| }, |
| [BCM_TOPO_PON_MODE_LOOPBACK] = |
| { |
| .if_validate = NULL, |
| .if_set = mac_util_interface_set_for_loopback, |
| .sub_term_validate = NULL, |
| .sub_term_set = mac_util_subscriber_terminal_set_for_loopback, |
| .flow_validate = NULL, |
| .flow_set = mac_util_flow_set_for_loopback, |
| .group_validate = NULL, |
| .group_set = NULL, |
| .sla_us_rate_factor = 1 |
| } |
| }; |
| |
| static f_bcmolt_msg_handler g_indication_handler; |
| |
| static bcm_topo_pon_mode mac_util_get_pon_mode(uint32_t logical_intf_id) |
| { |
| bcm_topo_pon_mode mode; |
| if (bcmbal_is_mac_in_loopback()) |
| mode = BCM_TOPO_PON_MODE_LOOPBACK; |
| else |
| mode = bcm_topo_pon_get_pon_mode(logical_intf_id); |
| return mode; |
| } |
| |
| static uint16_t oper_status_from_pon_state_get(uint32_t logical_intf_id, uint16_t state) |
| { |
| uint16_t oper_status; |
| bcm_topo_pon_family pon_family; |
| |
| pon_family = bcm_topo_pon_get_pon_family(logical_intf_id); |
| |
| switch (pon_family) |
| { |
| case BCM_TOPO_PON_FAMILY_EPON: |
| oper_status = (((bcmolt_epon_ni_en_state)state == BCMOLT_EPON_NI_EN_STATE_ENABLED) ? |
| BAL_UTIL_OPER_IF_UP : BAL_UTIL_OPER_IF_DOWN); |
| break; |
| |
| case BCM_TOPO_PON_FAMILY_GPON: |
| oper_status = (((bcmolt_pon_state)state == BCMOLT_PON_STATE_ACTIVE_WORKING) ? |
| BAL_UTIL_OPER_IF_UP : BAL_UTIL_OPER_IF_DOWN); |
| break; |
| |
| case BCM_TOPO_PON_FAMILY_INVALID: |
| default: |
| BCMOS_TRACE_ERR("Unknown PON family on intf %u: %d\n", logical_intf_id, pon_family); |
| oper_status = BAL_UTIL_OPER_IF_DOWN; |
| break; |
| } |
| |
| return oper_status; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief Function to send a util indication message to the core |
| * |
| * @param msg_payload A pointer to a well formed MAC util indication message |
| * |
| * @returns bcmos_errno == BCM_ERR_OK |
| * |
| *****************************************************************************/ |
| static bcmos_errno mac_util_ind_send(bal_util_msg_ind *msg_payload) |
| { |
| bcmos_errno rc; |
| |
| rc = bcmos_msg_dispatch(bcmbal_bcmos_hdr_get(msg_payload), BCMOS_MSG_SEND_AUTO_FREE); |
| |
| if (rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, |
| "Couldn't dispatch indication message from MAC util (%d:%d)\n", |
| (int)(bcmbal_bcmos_hdr_get(msg_payload))->type, |
| (int)(bcmbal_bcmos_hdr_get(msg_payload))->instance); |
| } |
| |
| return rc; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief Function to send a util auto indication message to the core |
| * |
| * @param msg_payload A pointer to a well formed MAC util indication message |
| * |
| * @returns bcmos_errno == BCM_ERR_OK |
| * |
| *****************************************************************************/ |
| static bcmos_errno mac_util_auto_ind_send(bal_util_msg_auto_ind *msg_payload) |
| { |
| bcmos_errno rc; |
| |
| rc = bcmos_msg_dispatch(bcmbal_bcmos_hdr_get(msg_payload), BCMOS_MSG_SEND_AUTO_FREE); |
| |
| if (rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, |
| "Couldn't dispatch auto indication message from MAC util (%d:%d)\n", |
| (int)(bcmbal_bcmos_hdr_get(msg_payload))->type, |
| (int)(bcmbal_bcmos_hdr_get(msg_payload))->instance); |
| } |
| |
| return rc; |
| } |
| |
| /* Report acc_term event */ |
| void mac_util_report_acc_term_event(uint16_t event) |
| { |
| bal_util_msg_ind *p_bal_util_ind_msg; |
| |
| if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind)))) |
| { |
| p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| |
| /* device connect */ |
| if (BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE == event) |
| { |
| p_bal_util_ind_msg->status = BCM_ERR_OK; |
| } |
| else |
| { |
| p_bal_util_ind_msg->status = BCM_ERR_PARM; |
| } |
| |
| bcmbal_msg_hdr_set(p_bal_util_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| BAL_MSG_TYPE_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_ACCESS_TERMINAL, |
| BAL_UTIL_OPER_ACC_TERM_CONNECT, |
| 0); |
| |
| BCM_LOG(INFO, log_id_mac_util, "Reporting to Core: BAL_UTIL_OPER_ACC_TERM_CONNECT indication. Status=%s\n", |
| bcmos_strerror(p_bal_util_ind_msg->status)); |
| |
| mac_util_ind_send(p_bal_util_ind_msg); |
| |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Could not allocate memory for access-terminal IND message\n"); |
| } |
| } |
| |
| |
| /** |
| * @brief Report interface event |
| * @note we consider both err and result for reporting the status to Core |
| * */ |
| void mac_util_report_if_event(bcmbal_intf_id intf_id, |
| bcmbal_intf_type intf_type, |
| bcmos_errno err, |
| bcmolt_result result, |
| bcmolt_pon_state new_state) |
| { |
| bal_util_msg_ind *p_bal_util_ind_msg; |
| |
| if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind)))) |
| { |
| |
| /** @todo validate inf_id is within range based on intf_type */ |
| p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| p_bal_util_ind_msg->obj_key.if_key.intf_id = intf_id; |
| p_bal_util_ind_msg->obj_key.if_key.intf_type = intf_type; |
| |
| if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != result)) |
| { |
| err = BCM_ERR_INTERNAL; |
| } |
| p_bal_util_ind_msg->status = err; |
| |
| bcmbal_msg_hdr_set(p_bal_util_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| BAL_MSG_TYPE_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_INTERFACE, |
| oper_status_from_pon_state_get(intf_id, new_state), |
| 0); |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_id), "Reporting to Core: interface id %d %s indication: %s\n", |
| intf_id, |
| (BAL_UTIL_OPER_IF_UP == oper_status_from_pon_state_get(intf_id, new_state)) ? "UP" : "DOWN", |
| bcmos_strerror(p_bal_util_ind_msg->status)); |
| |
| |
| mac_util_ind_send(p_bal_util_ind_msg); |
| |
| } |
| else |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_id), |
| "Could not allocate memory for interface IND message\n"); |
| } |
| } |
| |
| /* Report subscriber terminal event */ |
| |
| /** |
| * @note p_serial_number may be NULL and is only valid when an ONU |
| * is being reported as DISCOVERED |
| * @note result is config status reported by Maple, whereas err is messaging status |
| * between the MAC util & Maple |
| * */ |
| void mac_util_report_sub_term_event(bcmbal_intf_id pon_ni, |
| bcmbal_sub_id onu_id, |
| bcmolt_serial_number *p_serial_number, |
| bal_util_oper_sub_term oper, |
| bcmos_errno err, |
| bcmolt_result result, |
| bcmolt_activation_fail_reason fail_reason, |
| bcmolt_epon_tunnel_id tunnel_id) |
| { |
| bal_util_msg_ind *p_bal_util_ind_msg; |
| uint16_t total_msglen; |
| bcm_topo_pon_family pon_family; |
| |
| total_msglen = sizeof(bal_util_msg_ind); |
| |
| pon_family = bcm_topo_pon_get_pon_family(pon_ni); |
| /** |
| * @note if pon mode is invalid then this error should have been caught in the validation stage itself. |
| * However, still checking here to make sure and report an error if needed. |
| */ |
| if (pon_family == BCM_TOPO_PON_FAMILY_INVALID) |
| { |
| result = BCMOLT_RESULT_FAIL; |
| } |
| |
| if (pon_family == BCM_TOPO_PON_FAMILY_EPON) |
| { |
| total_msglen += sizeof(bcmolt_epon_tunnel_id); |
| } |
| else if(NULL != p_serial_number) |
| { |
| total_msglen += sizeof(bcmbal_serial_number); |
| } |
| |
| |
| /* consolidate "err" and "result" into one report status */ |
| if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != result)) |
| { |
| err = BCM_ERR_INTERNAL; |
| } |
| |
| |
| if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(total_msglen))) |
| { |
| /* set the object key */ |
| p_bal_util_ind_msg->obj_key.sub_term_key.intf_id = pon_ni; |
| p_bal_util_ind_msg->obj_key.sub_term_key.sub_term_id = onu_id; |
| |
| /* set bal util msg version */ |
| p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| |
| bcmbal_msg_hdr_set(p_bal_util_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| (BAL_UTIL_OPER_SUB_TERM_DISCOVERY == oper) ? BAL_MSG_TYPE_AUTO_IND : BAL_MSG_TYPE_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_SUBSCRIBER_TERMINAL, |
| oper, |
| 0); |
| |
| /* |
| * Set all the message header parameters |
| */ |
| if ((BCM_ERR_OK == err) && |
| (((BAL_UTIL_OPER_SUB_TERM_ADD == oper) && (fail_reason == BCMOLT_ACTIVATION_FAIL_REASON_NONE)) || |
| ((BAL_UTIL_OPER_SUB_TERM_ADD != oper) && (fail_reason == MAC_UTIL_DEACTIVATION_FAIL_REASON_NONE))) ) |
| { |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_ni), |
| "Reporting to Core: %s " |
| "indication from mac util: Success\n", |
| (BAL_UTIL_OPER_SUB_TERM_ADD == oper) ? "BAL_UTIL_OPER_SUB_TERM_ADD" : |
| (BAL_UTIL_OPER_SUB_TERM_REMOVE == oper) ? "BAL_UTIL_OPER_SUB_TERM_REMOVE" : |
| "BAL_UTIL_OPER_SUB_TERM_DISCOVERY"); |
| |
| p_bal_util_ind_msg->status = BCM_ERR_OK; |
| |
| if (pon_family == BCM_TOPO_PON_FAMILY_EPON) |
| { |
| memcpy(&p_bal_util_ind_msg->data, &tunnel_id, sizeof(bcmolt_epon_tunnel_id)); |
| } |
| else if (NULL != p_serial_number) |
| { |
| /* This assumes an identical definition of serial number between BAL and MAPLE */ |
| memcpy(&p_bal_util_ind_msg->data, p_serial_number, sizeof(bcmbal_serial_number)); |
| } |
| |
| } |
| else |
| { |
| p_bal_util_ind_msg->status = err; |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_ni), |
| "Reporting to Core: %s Indication from mac util: Failure, with status = %s, fail_reason = %d\n", |
| ((BAL_UTIL_OPER_SUB_TERM_ADD == oper) ? "BAL_UTIL_OPER_SUB_TERM_ADD" : |
| (BAL_UTIL_OPER_SUB_TERM_REMOVE == oper) ? "BAL_UTIL_OPER_SUB_TERM_REMOVE" : |
| "BAL_UTIL_OPER_SUB_TERM_DISCOVERY"), |
| bcmos_strerror(err), fail_reason); |
| } |
| |
| mac_util_ind_send(p_bal_util_ind_msg); |
| |
| } |
| else |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_ni), |
| "Could not allocate memory for subscriber-terminal IND message\n"); |
| } |
| } |
| |
| |
| /** |
| * Notify core flow FSM that flow add/modify/remove was success or failed |
| * |
| * @param flow_key |
| * @param pon_if pon interface |
| * @param op_type ADD, REMOVE, MODIFY |
| * @param err error code to be sent up |
| * |
| **/ |
| static void _mac_util_report_flow_set_indication(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type, bcmos_errno err) |
| { |
| bal_util_msg_ind *p_bal_util_ind_msg; |
| |
| if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind)))) |
| { |
| |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "Reporting to Core: flow %d, %s %s, result=%s\n", |
| flow_key.flow_id, |
| (BCMBAL_FLOW_TYPE_UPSTREAM == flow_key.flow_type ? "upstream" : |
| BCMBAL_FLOW_TYPE_DOWNSTREAM == flow_key.flow_type ? "downstream" : |
| BCMBAL_FLOW_TYPE_MULTICAST == flow_key.flow_type ? "multicast" :"broadcast"), |
| (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW ADD": |
| (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW REMOVE" : "FLOW_CLEAR")), |
| bcmos_strerror(err)); |
| |
| |
| /* set bal app p_msg version */ |
| p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| p_bal_util_ind_msg->obj_key.flow_key = flow_key; |
| p_bal_util_ind_msg->status = err; /* set the error code */ |
| |
| bcmbal_msg_hdr_set(p_bal_util_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| BAL_MSG_TYPE_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_FLOW, |
| op_type, |
| 0); |
| |
| |
| mac_util_ind_send(p_bal_util_ind_msg); |
| } |
| else |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "Could not allocate memory for flow IND message\n"); |
| } |
| } |
| |
| void mac_util_report_tm_sched_set_indication(bcmbal_tm_sched_key tm_sched_key, bcmos_errno err, bcmolt_result ind_result) |
| { |
| bal_util_msg_ind *p_bal_util_ind_msg; |
| |
| if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != ind_result)) |
| { |
| err = BCM_ERR_INTERNAL; |
| } |
| |
| if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind)))) |
| { |
| |
| BCM_LOG(INFO, log_id_mac_util, "Reporting to Core: tm sched %d, %s, result=%s\n", |
| tm_sched_key.id, |
| (BCMBAL_TM_SCHED_DIR_US == tm_sched_key.dir ? "upstream" :"downstream"), |
| bcmos_strerror(err)); |
| |
| |
| /* set bal app p_msg version */ |
| p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| p_bal_util_ind_msg->obj_key.tm_sched_key = tm_sched_key; |
| p_bal_util_ind_msg->status = err; /* set the error code */ |
| |
| bcmbal_msg_hdr_set(p_bal_util_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| BAL_MSG_TYPE_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_TM_SCHED, |
| BAL_UTIL_OPER_AGG_PORT_ADD, |
| 0); |
| |
| |
| mac_util_ind_send(p_bal_util_ind_msg); |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Could not allocate memory for tm sched IND message\n"); |
| } |
| } |
| |
| /** |
| * Notify core group FSM that group set request was success or failed |
| * |
| * @param group_key |
| * @param op_type ADD, REMOVE, SET, CREATE, DESTROY |
| * @param err error code to be sent up |
| * |
| **/ |
| static void _mac_util_report_group_set_indication (bcmbal_group_key group_key, bal_util_oper_group op_type, bcmos_errno err) |
| { |
| bal_util_msg_ind *p_bal_util_ind_msg; |
| |
| if(NULL != (p_bal_util_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_ind)))) |
| { |
| |
| BCM_LOG(INFO, log_id_mac_util, "Reporting to Core: group %d, %s, result=%s\n", |
| group_key.group_id, |
| BCMBAL_UTIL_GROUP_OPER_STR_GET(op_type), |
| bcmos_strerror(err)); |
| |
| |
| /* set bal app p_msg version */ |
| p_bal_util_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| p_bal_util_ind_msg->obj_key.group_key = group_key; |
| p_bal_util_ind_msg->status = err; /* set the error code */ |
| |
| bcmbal_msg_hdr_set(p_bal_util_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| BAL_MSG_TYPE_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_GROUP, |
| op_type, |
| 0); |
| |
| |
| mac_util_ind_send(p_bal_util_ind_msg); |
| } |
| else |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Could not allocate memory for group IND message\n"); |
| } |
| } |
| |
| /** |
| * Notify core flow FSM that flow operational state was changed |
| * |
| * @param pon_if - the flow interface |
| * @param flow_key |
| * @param op_type - relevant flow latest operation |
| * @param ind - success/fail represent current flow state is up/down |
| * |
| **/ |
| |
| void mac_util_report_flow_auto_ind (uint32_t pon_if, bcmbal_flow_key flow_key ,bal_util_oper_flow op_type, bal_util_flow_ind ind) |
| { |
| bal_util_msg_auto_ind *p_bal_util_auto_ind_msg; |
| |
| if(NULL != (p_bal_util_auto_ind_msg = bcmbal_msg_calloc(sizeof(bal_util_msg_auto_ind) + sizeof(bcmbal_status)))) |
| { |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(pon_if), "Reporting to Core: flow %d, %s %s, change to %s\n", |
| flow_key.flow_id, |
| (BCMBAL_FLOW_TYPE_UPSTREAM == flow_key.flow_type ? "upstream" : |
| BCMBAL_FLOW_TYPE_DOWNSTREAM == flow_key.flow_type ? "downstream" : |
| BCMBAL_FLOW_TYPE_MULTICAST == flow_key.flow_type ? "multicast" :"broadcast"), |
| (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW ADD": |
| (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW REMOVE" : "FLOW_CLEAR")), |
| ind == BAL_UTIL_FLOW_IND_SEND_FAIL ? "fail" : "success"); |
| |
| /* set bal app p_msg version */ |
| p_bal_util_auto_ind_msg->version = BAL_UTIL_MSG_VERSION; |
| p_bal_util_auto_ind_msg->obj_key.flow_key = flow_key; |
| |
| /*data will indicate the new operational state*/ |
| *(p_bal_util_auto_ind_msg->data) = ((ind == BAL_UTIL_FLOW_IND_SEND_FAIL) ? BCMBAL_STATUS_DOWN : BCMBAL_STATUS_UP); |
| p_bal_util_auto_ind_msg->status = BCM_ERR_OK; |
| |
| bcmbal_msg_hdr_set(p_bal_util_auto_ind_msg, |
| BCMBAL_MAC_UTIL_MSG, |
| BAL_MSG_TYPE_AUTO_IND, |
| BAL_SUBSYSTEM_MAC_UTIL, |
| BCMBAL_OBJ_ID_FLOW, |
| op_type, |
| 0); |
| |
| mac_util_auto_ind_send(p_bal_util_auto_ind_msg); |
| } |
| } |
| |
| |
| /** @brief Wrapper routine to Notify core flow FSM that flow ADD Success */ |
| void mac_util_report_flow_add_success(bcmbal_flow_key flow_key, uint32_t pon_if) |
| { |
| _mac_util_report_flow_set_indication(flow_key, pon_if, BAL_UTIL_OPER_FLOW_ADD, BCM_ERR_OK); |
| } |
| |
| /** @brief Wrapper routine to Notify core flow FSM that flow Add failed, based on result in indication msg from Maple */ |
| void mac_util_report_flow_add_failed(bcmbal_flow_key flow_key, uint32_t pon_if, bcmos_errno err) |
| { |
| _mac_util_report_flow_set_indication(flow_key, pon_if, BAL_UTIL_OPER_FLOW_ADD, err); |
| } |
| |
| /** @brief Wrapper routine to Notify core flow FSM that flow REMOVE is Success */ |
| void mac_util_report_flow_remove_success(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type) |
| { |
| _mac_util_report_flow_set_indication(flow_key, pon_if, op_type, BCM_ERR_OK); |
| } |
| |
| /** @brief Wrapper routine to Notify core flow FSM that flow Remove failed, based on result in indication msg from Maple */ |
| void mac_util_report_flow_remove_failed(bcmbal_flow_key flow_key, uint32_t pon_if, bal_util_oper_flow op_type, bcmos_errno err) |
| { |
| _mac_util_report_flow_set_indication(flow_key, pon_if, op_type, err); |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief mac_util_access_terminal_info_validate |
| * |
| * This routine is used to validate all input attributes required for an acc term |
| * setting received from the core. |
| * |
| * @param p_acc_term_req the acc term request info |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_access_terminal_info_validate(const bcmbal_access_terminal_cfg *p_acc_term_req) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| if (BCMOS_TRUE != BCMBAL_CFG_PROP_IS_SET(p_acc_term_req, access_terminal, iwf_mode)) |
| { |
| /* |
| * This is an error because the iwf mode is implicitly set by the core, based |
| * either on a parameter in the bal_config.txt file, or it is assigned a |
| * default value. Either way, this property must be set when this code |
| * executes. |
| */ |
| rc = BCM_ERR_PARM; |
| } |
| |
| return rc; |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief check_send_flow_bal_ind_msg |
| * the routine checks the indication status of a specific given flow, which its entry was just updated |
| * As flows may be 'waiting' for a single of few maple gem port configuration complete indications |
| * before an indication of complete flow setup can be indicated to bal_core |
| * |
| * @note this send routine is called multiple times for the scenario multiple flows per GEM/Alloc Id. |
| * |
| * @todo this routine currently assumes just flow add. This should handle a flow Remove case too |
| * |
| * @param p_flow - flow instance pointer from mac util DB |
| * @param err - remote error in msg from Maple |
| * @param ind_result - the status(BCMOLT_RESULT_SUCCESS/BCMOLT_RESULT_FAIL) of indication from Maple |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno check_send_flow_bal_ind_msg (flow_list_entry *p_flow, bcmos_errno err, bcmolt_result ind_result) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmos_bool send_ind = BCMOS_TRUE; |
| |
| /* for a ds flow, indication should be sent only if all constraints fulfilled: |
| indication was not sent yet |
| flow configuration completed - all related gem ports were configured to maple |
| all related gem ports configuration complete indication were received from device |
| */ |
| if (NULL == p_flow) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "%s: NULL flow passed in: flow\n", __FUNCTION__); |
| |
| return BCM_ERR_NOENT; |
| } |
| else |
| { |
| if (BCMOS_FALSE == p_flow->is_configuration_completed |
| || BCMOS_TRUE == p_flow->is_waiting_for_svc_port_active |
| || BAL_UTIL_FLOW_IND_SEND_NONE != p_flow->ind_sent) |
| { |
| send_ind = BCMOS_FALSE; |
| } |
| //else all conditions satisfied for sending an indication up to Core. |
| } |
| |
| if ((BCM_ERR_OK == err) && (BCMOLT_RESULT_SUCCESS != ind_result)) |
| { |
| err = BCM_ERR_INTERNAL; |
| } |
| |
| if (BCMOS_TRUE == send_ind) |
| { |
| switch (p_flow->op_type) |
| { |
| case BAL_UTIL_OPER_FLOW_ADD: |
| if (BCM_ERR_OK != err) |
| { |
| /* report flow failed to Core; It is upto the core to cleanup the flows */ |
| |
| p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_FAIL; |
| mac_util_report_flow_add_failed(p_flow->bal_flow_key, p_flow->if_id, err); |
| } |
| else |
| { |
| |
| p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_SUCCESS; |
| mac_util_report_flow_add_success(p_flow->bal_flow_key, p_flow->if_id); |
| } |
| |
| break; |
| |
| case BAL_UTIL_OPER_FLOW_REMOVE: |
| case BAL_UTIL_OPER_FLOW_CLEAR: |
| if (BCM_ERR_OK != err) |
| { |
| /* report flow failed to Core; It is upto the core to cleanup the flows */ |
| |
| p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_FAIL; |
| mac_util_report_flow_remove_failed(p_flow->bal_flow_key, p_flow->if_id, p_flow->op_type, err); |
| } |
| else |
| { |
| |
| p_flow->ind_sent = BAL_UTIL_FLOW_IND_SEND_SUCCESS; |
| mac_util_report_flow_remove_success(p_flow->bal_flow_key, p_flow->if_id, p_flow->op_type); |
| } |
| |
| /* One more step for Flow Remove: remove from DB & Free the flow */ |
| _mac_util_db_flow_remove (p_flow->if_id, p_flow); |
| _mac_util_db_flow_free (p_flow->if_id, p_flow); |
| |
| break; |
| |
| default: |
| rc = BCM_ERR_INTERNAL; |
| break; |
| } |
| } |
| |
| return rc; |
| } |
| |
| |
| /** |
| * @brief mac_util_indication_cb |
| * this routine is the callback function that is registered by mac_util_indication_handler_register() |
| * to handle any indications coming from maple device |
| * this is the entry point for the device towards mac_util/bal |
| * |
| * @param device_id the maple device id generating the current indication |
| * @param p_msg pointer to the maple indication message |
| * |
| * @return void |
| * |
| * @todo Note that the pon interface in Auto Indication msgs from Maple is a physical interface |
| * on a device. The PON interface that is used by Core in it's requests to MAC Util, |
| * and stored in local DBs will be logical interface. |
| * So the rule of thumb would be anything coming from Maple side, translate (device + physical Interface) |
| * to Logical interface and use for logging, internal DB access etc. |
| */ |
| void mac_util_indication_cb(bcmolt_devid device_id, bcmolt_msg *p_msg) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| switch (p_msg->obj_type) |
| { |
| case BCMOLT_OBJ_ID_DEVICE: |
| { |
| rc = mac_util_indication_handle_for_device (device_id, p_msg); |
| } |
| break; |
| |
| case BCMOLT_OBJ_ID_GPON_NI: |
| case BCMOLT_OBJ_ID_GPON_ONU: |
| case BCMOLT_OBJ_ID_GPON_ALLOC: |
| case BCMOLT_OBJ_ID_GPON_GEM_PORT: |
| { |
| rc = mac_util_handle_all_olt_ind_for_gpon (device_id, p_msg); |
| } |
| break; |
| |
| case BCMOLT_OBJ_ID_XGPON_NI: |
| case BCMOLT_OBJ_ID_XGPON_ONU: |
| case BCMOLT_OBJ_ID_XGPON_ALLOC: |
| { |
| rc = mac_util_handle_all_olt_ind_for_xgpon (device_id, p_msg); |
| } |
| break; |
| |
| default: |
| BCM_LOG(DEBUG, log_id_mac_util, "Unhandled message indication for obj type %d\n", |
| p_msg->obj_type); |
| |
| rc = BCM_ERR_INTERNAL; |
| break; |
| } |
| |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Error handling Auto Indication from Maple for obj type %d\n", p_msg->obj_type); |
| } |
| |
| return; |
| } |
| |
| |
| |
| /** |
| * @brief get string for the indication object type for device |
| */ |
| static char *mac_util_indication_get_obj_type_str_for_device (bcmolt_obj_id obj_type) |
| { |
| int i = 0; |
| for (i=0; i < BCM_SIZEOFARRAY(mac_util_device_ind_handlers); i++) |
| { |
| if (obj_type == mac_util_device_ind_handlers[i].obj_type) |
| { |
| return mac_util_device_ind_handlers[i].obj_type_str; |
| } |
| } |
| |
| return "Unhandled"; |
| } |
| |
| /** |
| * @brief check if mac util should report access terminal connect event to core. |
| * event will be sent only when all devices are connected successfully |
| * |
| * @return bcmos_bool |
| */ |
| |
| static bcmos_bool mac_util_check_acc_term_report_event (void) |
| { |
| |
| bcmolt_devid device_id; |
| |
| BCM_TOPO_FOR_EACH_DEV(device_id) |
| { |
| if (!acc_term_connectivity.devices[device_id].is_connected) |
| { |
| return BCMOS_FALSE; |
| } |
| } |
| return BCMOS_TRUE; |
| } |
| |
| /** |
| * @brief Handler function for Maple auto indications for a OLT Device |
| * |
| * @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_device (bcmolt_devid device_id, bcmolt_msg *p_msg) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| 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_device(p_msg->obj_type), |
| p_msg->group, p_msg->subgroup); |
| |
| if (BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE == p_msg->subgroup) |
| { |
| BCM_LOG(INFO, log_id_mac_util, "Device %u is ready.\n", device_id); |
| |
| acc_term_connectivity.devices[device_id].is_connected = BCMOS_TRUE; |
| |
| if (mac_util_check_acc_term_report_event()) |
| { |
| mac_util_report_acc_term_event(p_msg->subgroup); |
| } |
| |
| if (mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_post_indication_set) |
| { |
| rc = mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_post_indication_set(device_id); |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "%s: post indication set FAILED: rc = %s (%d)\n", |
| __FUNCTION__, bcmos_strerror(rc), rc); |
| } |
| } |
| } |
| else if (BCMOLT_DEVICE_AUTO_ID_CONNECTION_FAILURE == p_msg->subgroup) |
| { |
| BCM_LOG(INFO, log_id_mac_util, "Device %u connection failed.\n", device_id); |
| if(!acc_term_connectivity.fail_reported) |
| { |
| mac_util_report_acc_term_event(p_msg->subgroup); |
| } |
| acc_term_connectivity.fail_reported = BCMOS_TRUE; |
| } |
| |
| return rc; |
| } |
| |
| |
| /** |
| * @brief Common routine to get string of indication object |
| * |
| * @param obj_type obj type to get string for |
| * @param obj_types_and_handlers obj types array |
| * @param num_obj_types num obj types |
| * |
| * @return char* |
| */ |
| char *_mac_util_get_obj_type_str_for_indications ( bcmolt_obj_id obj_type, |
| mac_util_ind_obj_and_handlers obj_types_and_handlers[], uint16_t num_obj_types) |
| { |
| int i; |
| |
| for (i = 0; i < num_obj_types; i++) |
| { |
| if (obj_type == obj_types_and_handlers[i].obj_type) |
| { |
| return obj_types_and_handlers[i].obj_type_str; |
| } |
| } |
| |
| return "Unhandled"; |
| } |
| |
| |
| /** |
| * @brief Common routine to register for Maple auto indications |
| * |
| * @param p_rx_cfg handler config structure |
| * @param obj_types_and_handlers obj types to subscribe |
| * @param num_obj_types num obj types |
| * @param device_id specific device id (for multiple devices support) |
| * |
| * @return bcmos_errno |
| * |
| * @todo with multiple devices in future this needs to be done on per device basis and based on epon or gpon mode |
| */ |
| bcmos_errno _mac_util_register_for_auto_indications (struct bcmolt_rx_cfg *p_rx_cfg, |
| mac_util_ind_obj_and_handlers obj_types_and_handlers[], uint16_t num_obj_types, |
| bcmolt_devid device_id) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| int i; |
| |
| for (i = 0; i < num_obj_types; i++) |
| { |
| /* set to specific auto indication object type */ |
| p_rx_cfg->obj_type = obj_types_and_handlers[i].obj_type; |
| rc = bcmolt_auto_rx_cb_set(device_id, p_rx_cfg); |
| if (BCM_ERR_OK != rc) |
| { |
| return rc; |
| } |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| |
| /** |
| * @brief Maple auto indication register for specific device 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_device_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_device_ind_handlers, BCM_SIZEOFARRAY(mac_util_device_ind_handlers),device_id); |
| } |
| |
| |
| /** |
| * @brief mac_util_indication_handler_register |
| * this local routine registers the local function 'mac_util_indication_cb' |
| * as the callback for any indications coming from maple device |
| * |
| *@param device_id specific device id (for multiple devices support) |
| * |
| * @return bcmos_errno |
| */ |
| static bcmos_errno mac_util_indication_handler_register(bcmolt_devid device_id) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| struct bcmolt_rx_cfg rx_cfg = |
| { |
| .obj_type = BCMOLT_OBJECT_ANY, |
| .rx_cb = g_indication_handler, |
| .flags = BCMOLT_AUTO_FLAGS_DISPATCH, |
| .module = BCMOS_MODULE_ID_WORKER_MGMT, |
| .pon_ni_mask = 0 /** Bitmask of pon_ni interfaces the registration applies to. 0=all interfaces. */ |
| }; |
| |
| |
| rc = mac_util_register_for_device_auto_indications(&rx_cfg, device_id); |
| if (BCM_ERR_OK != rc) |
| { |
| return rc; |
| } |
| |
| rc = mac_util_register_for_gpon_auto_indications(&rx_cfg, device_id); |
| if (BCM_ERR_OK != rc) |
| { |
| return rc; |
| } |
| |
| rc = mac_util_register_for_xgpon_auto_indications(&rx_cfg, device_id); |
| if (BCM_ERR_OK != rc) |
| { |
| return rc; |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| |
| /** |
| * @brief reset mac_util access terminal internal db |
| * all devices marked as disconnected |
| */ |
| |
| static void mac_util_access_terminal_reset (void) |
| { |
| bcmolt_devid device_id; |
| |
| BCM_TOPO_FOR_EACH_DEV(device_id) |
| { |
| acc_term_connectivity.devices[device_id].is_connected = BCMOS_FALSE; |
| } |
| |
| acc_term_connectivity.fail_reported = BCMOS_FALSE; |
| } |
| |
| /** |
| * @brief reset a single maple device |
| * |
| * @param device_id the maple device id to be reset |
| * |
| * @return bcmos_errno |
| */ |
| |
| static bcmos_errno reset_device(bcmolt_devid device_id) |
| { |
| |
| bcmolt_device_key key = {}; |
| bcmolt_device_reset oper; |
| |
| BCMOLT_OPER_INIT(&oper, device, reset, key); |
| BCMOLT_OPER_PROP_SET(&oper, device, reset, mode, BCMOLT_DEVICE_RESET_MODE_DEVICE); |
| |
| return bcmolt_oper_submit(device_id , &oper.hdr); |
| } |
| |
| /** |
| * @brief common config across mac modes during access terminal set. |
| * currently only the admin up case is supported (op_type is ignored)) |
| * @note this is called from individual mac handler files rather than calling upfront here in this file |
| * in access_terminal_set(), because this is not to be called for loopback mode. |
| * |
| * |
| * @return bcmos_errno |
| */ |
| |
| bcmos_errno maple_access_terminal_set_common (acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type, bcmolt_devid device_id) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| |
| rc = reset_device(device_id); |
| if (rc != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Failed to reset device %d (%s)\n", device_id, bcmos_strerror(rc)); |
| return rc; |
| } |
| /* Because there is no indication coming from Maple that device reset is complete, we should sleep here. 1 second should be enough. */ |
| bcmos_usleep(1000000); |
| |
| /* register for maple indications - doing it after reset to avoid catching stale indications */ |
| rc = mac_util_indication_handler_register(device_id); |
| if (rc != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Failed to register for device %d indications (%s)\n", device_id, bcmos_strerror(rc)); |
| return rc; |
| } |
| /* using 1 second delay between the indication registration and configuration setup |
| to let the maple proxy queue get empty */ |
| bcmos_usleep(1000000); |
| |
| return BCM_ERR_OK; |
| } |
| |
| bcmos_errno maple_access_terminal_connect_common (bcmolt_devid device_id) |
| { |
| bcmos_errno rc; |
| bcmolt_device_connect dev_connect_oper; |
| bcmolt_device_key key = {}; |
| |
| /* invoking the connect operation */ |
| BCMOLT_OPER_INIT(&dev_connect_oper, device, connect, key); |
| |
| rc = bcmolt_oper_submit(device_id, &dev_connect_oper.hdr); |
| if (rc != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Failed to submit connect operation for device %d (%s), err_text = %s\n", |
| device_id, bcmos_strerror(rc), dev_connect_oper.hdr.hdr.err_text); |
| } |
| |
| return rc; |
| } |
| |
| /* Derive a specific device system mode from topology and store it at the internal db*/ |
| static bcmos_errno mac_util_system_mode_get(bcmolt_devid device_id) |
| { |
| uint32_t logical_pon; |
| uint32_t pon_mode2max_physical_pons[BCM_TOPO_PON_MODE__NUM_OF] = {}; |
| |
| BCM_TOPO_DEV_FOR_EACH_PON(device_id, logical_pon) |
| { |
| uint32_t physical_pon; |
| bcm_topo_pon_mode pon_mode; |
| |
| pon_mode = bcm_topo_pon_get_pon_mode(logical_pon); |
| bcm_topo_pon_get_logical2physical(logical_pon, &device_id, &physical_pon); |
| /* Get the number of physical PONs mapped. |
| * For example, if the user mapped only 4 physical PONs out of 16 in GPON mode, and the maximum physical PON mapped was 11, then the system mode should be GPONx16, not GPONx8. */ |
| pon_mode2max_physical_pons[pon_mode] = MAX(pon_mode2max_physical_pons[pon_mode], physical_pon + 1); |
| |
| } |
| |
| if (bcmbal_is_mac_in_loopback()) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_LOOPBACK; |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_GPON]) |
| { |
| if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_GPON] <= 8) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_GPON__8_X; |
| else |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_GPON__16_X; |
| } |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_XGPON]) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_XGPON_1__8_X; |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_XGS]) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_XGS__2_X_10_G; |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_TDMA]) |
| { |
| if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_TDMA] <= 4) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__4_X_COEXISTENCE_TDMA; |
| else |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__8_X_COEXISTENCE_TDMA; |
| } |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_1G]) |
| { |
| if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_1G] <= 4) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__4_X; |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_1G] <= 8) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__8_X; |
| else |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__16_X; |
| } |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_10G]) |
| { |
| if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_10G] <= 2) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__2_X_10_G; |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_EPON_10G] <= 4) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__4_X_10_G; |
| else |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_EPON__8_X_10_G; |
| } |
| else if (pon_mode2max_physical_pons[BCM_TOPO_PON_MODE_LOOPBACK]) |
| acc_term_connectivity.devices[device_id].system_mode = BCMOLT_SYSTEM_MODE_LOOPBACK; |
| else |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Cannot determine system mode from topology\n"); |
| return BCM_ERR_PARM; |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| /** |
| * @brief Command Set setup routine for access terminal connect to the mac devices |
| * |
| * This routine is called by acc_term_fsm in the BAL core, at an admin up operation |
| * and will result in setting and connecting all the access terminal devices |
| * |
| * @param p_acc_term Pointer to access terminal instance |
| * @param op_type Operation type on access terminal instance |
| * |
| * @return bcmos_errno |
| * |
| * @todo this code will change with multiple devices |
| */ |
| bcmos_errno mac_util_access_terminal_set(acc_term_inst *p_acc_term, bal_util_oper_acc_term op_type) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmolt_devid device_id; |
| bcmos_bool is_wait_for_report = BCMOS_FALSE; |
| |
| BCM_TOPO_FOR_EACH_DEV(device_id) |
| { |
| /*will reset and connect, in case the device is not already connected*/ |
| if (!acc_term_connectivity.devices[device_id].is_connected) |
| { |
| /* Add timeout between bringing up maple devices. |
| * Otherwise, maple APIs can time out |
| */ |
| if (is_wait_for_report) |
| bcmos_usleep(10000000); |
| is_wait_for_report = BCMOS_TRUE; |
| /* mac mode specific acc term set */ |
| if (mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_set) |
| { |
| rc = mac_util_bal_req_handlers_for_system_mode[acc_term_connectivity.devices[device_id].system_mode].acc_term_set(p_acc_term, op_type, device_id); |
| } |
| |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "%s: FAILED: rc = %s (%d)\n", |
| __FUNCTION__, bcmos_strerror(rc), rc); |
| return rc; |
| } |
| } |
| } |
| if (!is_wait_for_report) |
| { |
| mac_util_report_acc_term_event(BCMOLT_DEVICE_AUTO_ID_CONNECTION_COMPLETE); |
| } |
| |
| return rc; |
| } |
| |
| /*---------------------------------------------------------------------------------------------*/ |
| /*----------------------------------interface set handling-------------------------------------------*/ |
| |
| /** |
| * @brief Command Set setup routine for interface up to mac application |
| * |
| * 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 interface instance |
| * |
| * @return bcmos_errno |
| * |
| * @todo system mode to identify handler function is global across olt now. |
| * This should be queried for per pon interface and used to identify the protocol |
| * and the corresponding handler. |
| */ |
| bcmos_errno mac_util_interface_set(acc_term_interface *p_interface_inst, bal_util_oper_if op_type) |
| { |
| /* Parameter checks */ |
| BUG_ON(NULL == p_interface_inst); |
| |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmbal_interface_key intf_key = p_interface_inst->api_req_int_obj_info.key; |
| bcm_topo_pon_mode pon_mode; |
| |
| /* First check if it is for PON interface. If not (i.e. NNI), then just return a success without |
| * forwarding anything to MAC hardware. |
| */ |
| if (BCMBAL_INTF_TYPE_PON != intf_key.intf_type) |
| { |
| mac_util_report_if_event(intf_key.intf_id, |
| intf_key.intf_type, |
| BCM_ERR_OK, BCMOLT_RESULT_SUCCESS, |
| ((BAL_UTIL_OPER_IF_UP == op_type) ? BCMOLT_PON_STATE_ACTIVE_WORKING : BCMOLT_PON_STATE_INACTIVE)); |
| |
| return BCM_ERR_OK; |
| } |
| |
| BCM_LOG(DEBUG, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id), |
| "SET if %s , intf_type: %s, intf_id: %d\n", |
| (BAL_UTIL_OPER_IF_UP == op_type ? "UP" : "DOWN"), |
| (BCMBAL_INTF_TYPE_PON == intf_key.intf_type ? "PON":"NNI"), |
| intf_key.intf_id); |
| |
| /* query PON mode */ |
| pon_mode = mac_util_get_pon_mode(intf_key.intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| rc = BCM_ERR_INTERNAL; |
| |
| /* system mode specific interface set */ |
| if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].if_set) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].if_set(p_interface_inst, op_type); |
| } |
| |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(intf_key.intf_id), |
| "Failed 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_subscriber_terminal_info_validate |
| * |
| * This routine is used to validate all input attributes required for a sub term setting |
| * received from core |
| * |
| * @param p_sub_term_req A pointer to a subscriber terminal object |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_subscriber_terminal_info_validate(const bcmbal_subscriber_terminal_cfg *p_sub_term_req) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcm_topo_pon_mode pon_mode; |
| |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_sub_term_req->key.intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| rc = BCM_ERR_INTERNAL; |
| |
| /* validate system mode specific things */ |
| if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_validate) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_validate(p_sub_term_req); |
| } |
| |
| return rc; |
| } |
| |
| |
| /*----------------------------------subscriber terminal set handling-----------------------------------*/ |
| |
| /** |
| * @brief Command Set setup routine for subscriber terminal connect to mac application |
| * |
| * 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 request is after a ONU Discovery |
| * |
| * @return bcmos_errno |
| */ |
| |
| bcmos_errno mac_util_subscriber_terminal_set(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_topo_pon_mode pon_mode; |
| |
| 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; |
| } |
| |
| |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_sub_term_req->key.intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| rc = BCM_ERR_INTERNAL; |
| |
| /* system mode specific sub term set */ |
| if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_set) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].sub_term_set(p_sub_term_inst, op_type, is_post_discovery); |
| } |
| |
| |
| 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; |
| } |
| |
| |
| |
| |
| /*---------------------------------------------------------------------------------------------*/ |
| /*------------------group set handling GROUP routines and helper functions-------------------*/ |
| /*---------------------------------------------------------------------------------------------*/ |
| |
| /*****************************************************************************/ |
| /** |
| * @brief mac_util_group_info_validate |
| * |
| * This routine is used to validate all input attributes required for a group |
| * setting received from core |
| * |
| * @param p_group_req A pointer to a group object |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_group_info_validate(const bcmbal_group_cfg *p_group_req) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| int i; |
| |
| do |
| { |
| /* if the group has no owner, no need to check as service port will not be assigned */ |
| if (p_group_req->data.owner == BCMBAL_GROUP_OWNER_NONE) |
| { |
| break; |
| } |
| /* if group member command is set, there has to be member info, |
| for remove, service port is an option |
| */ |
| if (BCMBAL_CFG_PROP_IS_SET(p_group_req, group, members_cmd)) |
| { |
| if(p_group_req->data.members.len) |
| { |
| for(i=0; i< p_group_req->data.members.len; i++) |
| { |
| /* all members should have the service port as non-zero */ |
| if (!p_group_req->data.members.val[i].svc_port_id) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, |
| "svc_port_id is a mandatory parameter for a group member, and it can not set to zero\n"); |
| rc = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| break; |
| } |
| } |
| } |
| } |
| |
| }while(0); |
| |
| return rc; |
| } |
| |
| /** |
| * @brief Core interface: setup routine for group |
| * |
| * This routine is called by group_fsm in the BAL core to |
| * add/remove/set group in the mac application. Unlike flow request, |
| * the mac driver does not send indication messages back upon completion. |
| * This routine needs to fake an indication message to core to trigger the group_fsm. |
| * |
| * @param p_grp_inst Pointer to group instance |
| * @param op_type Operation type on group instance |
| * @param send_ind TRUE - send indication, FALSE - don't send indication |
| * |
| * @return bcmos_errno |
| */ |
| bcmos_errno mac_util_group_set(group_inst *p_grp_inst, bal_util_oper_group op_type, bcmos_bool send_ind) |
| { |
| bcmbal_group_cfg *p_group_req = &p_grp_inst->api_req_group_info; |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmbal_group_cfg *p_group_lookup_info = NULL; |
| bcm_topo_pon_mode pon_mode; |
| |
| do |
| { |
| /* if the group has no owner, no need to access the HW as service port will not be set */ |
| if (p_group_req->data.owner == BCMBAL_GROUP_OWNER_NONE) |
| { |
| break; |
| } |
| |
| /* |
| * When we are doing a GROUP_ADD, the API request has the information we need, |
| * When we are doing a GROUP_DESTROY, the current group info has this information (because |
| * the GROUP_DESTROY request only has the group key populated. The current flow info has |
| * all of the attributes used when create the group. |
| */ |
| p_group_lookup_info = (BAL_UTIL_OPER_GROUP_DESTROY == op_type) ? &p_grp_inst->current_group_info : p_group_req; |
| |
| BCM_LOG(INFO, log_id_mac_util, "%s group_id = %d with oper type %s\n ", |
| __FUNCTION__, |
| p_group_lookup_info->key.group_id, |
| BCMBAL_UTIL_GROUP_OPER_STR_GET(op_type) |
| ); |
| |
| /* mac only need to response to set member when op_type is ADD/REMOVE/SET - configure multicast service ports */ |
| if ((BAL_UTIL_OPER_GROUP_ADD == op_type || |
| BAL_UTIL_OPER_GROUP_REMOVE == op_type || |
| BAL_UTIL_OPER_GROUP_SET == op_type ) && |
| BCMBAL_CFG_PROP_IS_SET(p_group_req, group, members)) |
| { |
| /* assume all members are of same mode */ |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_group_req->data.members.val[0].intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| { |
| rc = BCM_ERR_INTERNAL; |
| } |
| /* system mode specific group set */ |
| else if ( mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set(p_group_req, op_type, p_grp_inst); |
| } |
| |
| } |
| |
| /* special case - destroy with valid members, then need to remove all members */ |
| else if ((BAL_UTIL_OPER_GROUP_DESTROY == op_type && p_group_lookup_info->data.members.len != 0)) |
| { |
| /* query system mode - use first member as default */ |
| pon_mode = mac_util_get_pon_mode(p_group_lookup_info->data.members.val[0].intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| { |
| rc = BCM_ERR_INTERNAL; |
| } |
| /* system mode specific group set */ |
| else if ( mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].group_set(p_group_lookup_info, BAL_UTIL_OPER_GROUP_REMOVE, p_grp_inst); |
| } |
| } |
| }while(0); |
| |
| /* return an indication message to core */ |
| if(send_ind) |
| { |
| _mac_util_report_group_set_indication(p_group_req->key, op_type, rc); |
| } |
| |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, |
| "%s Failed: rc = %s (%d)\n", |
| __FUNCTION__, |
| bcmos_strerror(rc), rc); |
| } |
| |
| return rc; |
| } |
| |
| |
| /*---------------------------------------------------------------------------------------------*/ |
| /*------------------flow set handling Interface routines and helper functions-------------------*/ |
| /*---------------------------------------------------------------------------------------------*/ |
| |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief mac_util_flow_info_validate |
| * |
| * This routine is used to validate all input attributes required for a flow |
| * setting received from core |
| * |
| * @param p_flow_req A pointer to a flow object |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_flow_info_validate(const bcmbal_flow_cfg *p_flow_req) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcm_topo_pon_mode pon_mode; |
| |
| do |
| { |
| if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_MULTICAST) |
| { |
| /* nothing to do in multicast FLOW - validate in GROUP*/ |
| break; |
| } |
| if (p_flow_req->key.flow_type == BCMBAL_FLOW_TYPE_DOWNSTREAM && |
| BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, group_id) ) |
| { |
| /* nothing to do in DS N:1 FLOW - validate in GROUP */ |
| break; |
| } |
| |
| if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, access_int_id)) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, |
| "access if id is a mandatory parameter for a flow, and it is not set\n"); |
| rc = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| |
| break; /* if interface id not set then skip rest of the checks */ |
| } |
| |
| if (p_flow_req->key.flow_type != BCMBAL_FLOW_TYPE_BROADCAST) |
| { |
| if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, sub_term_id)) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id), |
| "sub term id is a mandatory parameter for a flow, and it is not set\n"); |
| rc = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| } |
| } |
| |
| if (!BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, svc_port_id)) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id), |
| "svc_port_id is a mandatory parameter for a flow, and it is not set\n"); |
| rc = BCM_ERR_MANDATORY_PARM_IS_MISSING; |
| } |
| |
| /* validate flow id */ |
| if (BCMOS_FALSE == MAC_UTIL_FLOW_DB_FLOW_ID_IS_VALID(p_flow_req->key.flow_id)) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id), |
| "flow Id from user is not within range: %d <= flow id <= %d\n", |
| MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL); |
| rc = BCM_ERR_PARM; |
| } |
| |
| |
| |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_flow_req->data.access_int_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| { |
| rc = BCM_ERR_INTERNAL; |
| |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id), |
| "could not get system mode for pon interface\n"); |
| } |
| } |
| |
| /* system mode specific validation */ |
| if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_validate) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_validate(p_flow_req); |
| /* the called function will log any protocol specific validation errors */ |
| } |
| |
| } while (0); |
| |
| return rc; |
| } |
| |
| /** |
| * @brief Core interface: setup routine for flow |
| * |
| * This routine is called by flow_fsm in the BAL core to initialize the command |
| * to add flow to the mac application. The cmdset actually |
| * consists of two commands, one is to send the flow 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_flow_core Pointer to flow instance from core fsm |
| * @param op_type Operation type on flow instance |
| * |
| * @return bcmos_errno |
| */ |
| bcmos_errno mac_util_flow_set(flow_inst *p_flow_core, bal_util_oper_flow op_type) |
| { |
| bcmbal_flow_cfg *p_flow_req = &p_flow_core->api_req_flow_info; |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| bcmbal_flow_cfg *p_flow_lookup_info = NULL; |
| bcm_topo_pon_mode pon_mode; |
| |
| /* |
| * When we are doing a FLOW_ADD, the API request has the information we need, |
| * When we are doing a FLOW_REMOVE, the current flow info has this information (because |
| * the FLOW_REMOVE request only has the flow key populated. The current flow info has |
| * all of the attributes used to create the flow in the first place. |
| */ |
| p_flow_lookup_info = (BAL_UTIL_OPER_FLOW_ADD == op_type) ? p_flow_req : &p_flow_core->current_flow_info; |
| |
| bcmos_bool flow_is_destined_to_host = BAL_UTIL_OPER_FLOW_ADD == op_type ? |
| |
| ((BCMBAL_CFG_PROP_IS_SET(&p_flow_core->api_req_flow_info, flow, action) && |
| (p_flow_core->api_req_flow_info.data.action.cmds_bitmask & |
| BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE) : |
| |
| ((BCMBAL_CFG_PROP_IS_SET(&p_flow_core->current_flow_info, flow, action) && |
| (p_flow_core->current_flow_info.data.action.cmds_bitmask & |
| BCMBAL_ACTION_CMD_ID_TRAP_TO_HOST)) ? BCMOS_TRUE : BCMOS_FALSE); |
| |
| /* There's no need to do anything with the MAC in downstream flows that |
| * that are destined to the host CPU (i.e. NNI->CPU) |
| */ |
| if(((BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type) && |
| flow_is_destined_to_host)) |
| { |
| /* When the flow is downstream and destined to the host (i.e. NNI->CPU), then there |
| * is nothing to do in the MAC, so just return an indication to allow the FSM to continue on. |
| */ |
| if (BAL_UTIL_OPER_FLOW_ADD == op_type) |
| { |
| mac_util_report_flow_add_success(p_flow_req->key, p_flow_req->data.access_int_id); |
| } |
| else if ((BAL_UTIL_OPER_FLOW_REMOVE == op_type) || (BAL_UTIL_OPER_FLOW_CLEAR == op_type)) |
| { |
| mac_util_report_flow_remove_success(p_flow_req->key, p_flow_req->data.access_int_id, op_type); |
| } |
| } |
| /* for multicast flow all works are done in GROUP object, simply send the indication to Core */ |
| else if (BCMBAL_FLOW_TYPE_MULTICAST == p_flow_req->key.flow_type) |
| { |
| /* there is no access_int_id for multicast flow, pass 0 as parameter. |
| The interface number is just used for logging purpose in the indication API */ |
| _mac_util_report_flow_set_indication(p_flow_req->key, 0, op_type, rc); |
| } |
| /* for downstream n:1 flow all works are done in GROUP object, simply send the indication to Core */ |
| else if (BCMBAL_FLOW_TYPE_DOWNSTREAM == p_flow_req->key.flow_type && |
| (BCMBAL_CFG_PROP_IS_SET(p_flow_req, flow, group_id)) ) |
| { |
| /* there is no access_int_id for DS N:1 flow, pass 0 as parameter. |
| The interface number is just used for logging purpose in the indication API */ |
| _mac_util_report_flow_set_indication(p_flow_req->key, 0, op_type, rc); |
| } |
| else |
| { |
| |
| BCM_LOG(INFO, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_flow_req->data.access_int_id), |
| "%s flow_id = %d dir = %s, pon_id = %d " |
| "onu_id= %d alloc_id = %d gem_port = %d, op_type = %s\n", |
| __FUNCTION__, |
| p_flow_lookup_info->key.flow_id, |
| p_flow_lookup_info->key.flow_type == BCMBAL_FLOW_TYPE_UPSTREAM ? "up":"down", |
| p_flow_lookup_info->data.access_int_id, |
| p_flow_lookup_info->data.sub_term_id, |
| p_flow_lookup_info->data.agg_port_id, |
| p_flow_lookup_info->data.svc_port_id, |
| (BAL_UTIL_OPER_FLOW_ADD == op_type ? "FLOW_ADD": |
| (BAL_UTIL_OPER_FLOW_REMOVE == op_type ? "FLOW_REMOVE" : "FLOW_CLEAR"))); |
| |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_flow_req->data.access_int_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| rc = BCM_ERR_INTERNAL; |
| |
| /* system mode specific flow set */ |
| if ((BCM_ERR_OK == rc) && mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_set) |
| { |
| rc = mac_util_bal_req_handlers_for_pon_mode[pon_mode].flow_set(p_flow_lookup_info, op_type, p_flow_core); |
| } |
| } |
| |
| |
| 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: rc = %s (%d)\n", |
| __FUNCTION__, |
| bcmos_strerror(rc), rc); |
| } |
| |
| return rc; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief mac_util_tm sched_info_validate |
| * |
| * This routine is used to validate all input attributes required for a tm sched |
| * setting received from core |
| * |
| * @param p_tm_sched_req A pointer to a tm sched object |
| * |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_tm_sched_info_validate(const bcmbal_tm_sched_cfg *p_tm_sched_req) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcm_topo_pon_mode pon_mode; |
| do |
| { |
| if (!BCMBAL_CFG_PROP_IS_SET(p_tm_sched_req, tm_sched, owner)) |
| { |
| /* nothing to do in MAC */ |
| break; |
| } |
| |
| if (p_tm_sched_req->data.owner.type != BCMBAL_TM_SCHED_OWNER_TYPE_AGG_PORT) |
| { |
| /* nothing to do in MAC */ |
| break; |
| } |
| |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_tm_sched_req->data.owner.u.agg_port.intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| rc = BCM_ERR_INTERNAL; |
| |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, MAC_UTIL_GET_LOG_ID_FOR_PON_IF(p_tm_sched_req->data.owner.u.agg_port.intf_id), |
| "could not get system mode for pon interface\n"); |
| } |
| } while (0); |
| return rc; |
| } |
| |
| bcmos_errno mac_util_agg_port_set(tm_sched_inst *p_tm_sched, bal_util_oper_agg_port op_type) |
| { |
| bcmbal_tm_sched_cfg *p_agg_port_req = &p_tm_sched->req_tm_sched_info; |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| |
| bcm_topo_pon_mode pon_mode; |
| do |
| { |
| |
| /* query system mode */ |
| pon_mode = mac_util_get_pon_mode(p_agg_port_req->data.owner.u.agg_port.intf_id); |
| if (pon_mode == BCM_TOPO_PON_MODE_INVALID) |
| { |
| rc = BCM_ERR_INTERNAL; |
| break; |
| } |
| rc = maple_mac_util_agg_port_set(p_agg_port_req, op_type, p_tm_sched); |
| |
| }while(0); |
| return rc; |
| } |
| |
| #if !defined(WRX_BUILD) |
| /* Internal function that finds UDP port to bind to */ |
| static bcmos_errno _mac_util_find_free_udp_port(uint16_t *p_port) |
| { |
| #define MAX_UDP_PORT_TRY_ITER 100 /* Try 100 times, then give up */ |
| #define MAX_UDP_PORT 60000 |
| #define MIN_UDP_PORT (MAX_UDP_PORT / 2) |
| uint16_t port; |
| struct sockaddr_in sa; |
| int sock; |
| int bind_rc; |
| int i = 0; |
| |
| /* Open UDP socket */ |
| sock = socket(AF_INET, SOCK_DGRAM, 0); |
| if (sock < 0) |
| { |
| BCMOS_TRACE_RETURN(BCM_ERR_PARM, "Can't create UDP socket. error %s\n", strerror(errno)); |
| } |
| |
| memset(&sa, 0, sizeof(sa)); |
| sa.sin_family = AF_INET; |
| sa.sin_addr.s_addr = INADDR_ANY; |
| |
| do |
| { |
| port = rand() % MAX_UDP_PORT; |
| if (port < MIN_UDP_PORT) |
| port += MIN_UDP_PORT; |
| sa.sin_port = htons(port); |
| bind_rc = bind(sock, (struct sockaddr *)&sa, sizeof(sa)); |
| } while (bind_rc < 0 && ++i < MAX_UDP_PORT_TRY_ITER); |
| |
| /* Yes, yes. There is a possible race condition that someone will take the port we've just found |
| * before we had a chance to bind it again. |
| * In this unlikely case BAL application will fail on startup and will have to be restarted. |
| */ |
| close(sock); |
| |
| if (bind_rc < 0) |
| { |
| BCMOS_TRACE_RETURN(BCM_ERR_NORES, "Couldn't find unused UDP port after %d tries. Giving up.\n", i); |
| } |
| |
| *p_port = port; |
| |
| return BCM_ERR_OK; |
| } |
| #endif |
| |
| static void bal_indication_cb(bcmolt_devid olt, bcmolt_msg *p_msg) |
| { |
| mac_util_indication_cb(olt, p_msg); |
| |
| bcmolt_msg_free(p_msg); |
| } |
| |
| #ifdef ENABLE_LOG |
| /** |
| * @brief routine to register per pon log strings with logger |
| * |
| * @param system_mode -OLT system mode |
| * |
| * @return bcmos_errno |
| */ |
| static bcmos_errno mac_util_register_logging_per_pon (void) |
| { |
| char log_str_buf[MAC_UTIL_LOG_STR_SZ] = {0}; |
| bcmolt_devid device_id; |
| uint32_t logical_pon; |
| |
| /** @note if by any chance the system mode is set multiple times, then we want to avoid |
| * re-registering already registered pon interfaces, because there is currently no way |
| * to de-register those interfaces first. We will just register the not-registered ones. |
| */ |
| /* register log Ids for each PON interface, that is not already registered */ |
| BCM_TOPO_FOR_EACH_PON(device_id, logical_pon) |
| { |
| if (0 != log_id_mac_util_pon_if[logical_pon]) |
| { |
| continue; |
| } |
| |
| /* make a log id string */ |
| MAC_UTIL_MAKE_LOG_STR_FOR_PON_IF(logical_pon, log_str_buf, sizeof(log_str_buf)); |
| /* register log id string for pon interface */ |
| log_id_mac_util_pon_if[logical_pon] = bcm_dev_log_id_register(log_str_buf, DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| BUG_ON(log_id_mac_util_pon_if[logical_pon] == DEV_LOG_INVALID_ID); |
| } |
| |
| return BCM_ERR_OK; |
| } |
| #endif |
| |
| |
| |
| /** |
| * @brief get ip & port for MAC/Maple |
| */ |
| bcmos_errno mac_util_init_parse_mac_ip_and_port (const char *maple_address) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| #if !defined(WRX_BUILD) |
| rc = app_util_parse_ip_port(maple_address, &bcmtr_olt_ip[0], &bcmtr_olt_udp_port[0]); |
| if (rc) |
| { |
| return rc; |
| } |
| |
| srand(bcmos_timestamp()); |
| rc = _mac_util_find_free_udp_port(&bcmtr_host_udp_port); |
| #endif |
| |
| return rc; |
| } |
| |
| |
| /** |
| * @brief mac_util_init routine for mac application |
| * @param maple_address - pointer to maple device instance |
| * @return bcmos_errno |
| */ |
| bcmos_errno mac_util_init(const char *maple_address) |
| { |
| bcmos_errno rc = BCM_ERR_OK; |
| bcmolt_devid device_id; |
| |
| do |
| { |
| #ifdef ENABLE_LOG |
| /* register a generic MAC util log Id too, for use other than PON If related logs */ |
| log_id_mac_util = bcm_dev_log_id_register("MAC_UTIL", DEV_LOG_LEVEL_INFO, DEV_LOG_ID_TYPE_BOTH); |
| BUG_ON(log_id_mac_util == DEV_LOG_INVALID_ID); |
| #endif |
| |
| if (!bcmbal_is_mac_in_loopback()) |
| { |
| rc = mac_util_init_parse_mac_ip_and_port (maple_address); |
| if (BCM_ERR_OK != rc) |
| break; |
| } |
| |
| g_indication_handler = bal_indication_cb; |
| |
| BCM_TOPO_FOR_EACH_DEV(device_id) |
| { |
| rc = mac_util_system_mode_get(device_id); |
| if (BCM_ERR_OK != rc) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "%s: system mode get for device %d FAILED: rc = %s (%d)\n", |
| __FUNCTION__, device_id, bcmos_strerror(rc), rc); |
| break; |
| } |
| } |
| |
| #ifdef ENABLE_LOG |
| /* register logging for each PON based on mac mode*/ |
| mac_util_register_logging_per_pon(); |
| #endif |
| |
| mac_util_access_terminal_reset(); |
| |
| } while(0); |
| |
| return rc; |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief This function is the helper for the mac app print_flows CLI command backend |
| * which print the full internal flows list |
| * |
| * @param sess Pointer to the current cli session |
| * @param parm An array of parameters from the CLI command, which will be empty on that no parameters command case |
| * @param nParms The number of elements in the parm array (above) that have |
| * valid data, which will be 0 on that case. |
| * |
| * @returns BCM_ERR_OK on success, other bcmos_errno codes otherwise |
| * |
| *****************************************************************************/ |
| static bcmos_errno _cmd_flows_print(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms) |
| { |
| flow_list_entry *p_current_entry = NULL; |
| flow_list_entry *p_next_entry = NULL; |
| uint32_t if_id = 0; |
| |
| printf("Flow DB: starting flow id=%d, max flow id=%d\n", |
| MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL); |
| |
| for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++) |
| { |
| /* before every db segment, NULL the current entry */ |
| p_current_entry = NULL; |
| p_next_entry = NULL; |
| |
| /* get first */ |
| p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry); |
| while (NULL != p_current_entry) |
| { |
| printf("\n------------------------------\n"); |
| printf ("\nflow_id = %d flow_type = %d\n", p_current_entry->bal_flow_key.flow_id, p_current_entry->bal_flow_key.flow_type); |
| printf ("\n if_id = %d sub_term_id = %d svc_port_id = %d agg_id = %d vlan_id = %d\n", |
| p_current_entry->if_id, p_current_entry->sub_term_id, p_current_entry->svc_port_id, p_current_entry->agg_id, p_current_entry->vlan_id); |
| printf("\n is_waiting_for_svc_port_active = %s is_configuration_completed=%s ind_sent = %d\n", |
| p_current_entry->is_waiting_for_svc_port_active==BCMOS_TRUE ? "true" : "false", |
| p_current_entry->is_configuration_completed==BCMOS_TRUE ? "true" : "false", |
| p_current_entry->ind_sent); |
| printf("\n------------------------------\n"); |
| |
| /* get next */ |
| p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry); |
| } |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| static bcmos_errno _cmd_flows_print_for_gem(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms) |
| { |
| flow_list_entry *p_current_entry = NULL; |
| void *p_rsc_mgr_curr_entry = NULL; |
| void *p_rsc_mgr_next_entry = NULL; |
| |
| uint32_t if_id = 0; |
| |
| printf("Flow DB for a GEM port [%ld]: starting flow id=%d, max flow id=%d\n", |
| parm[0].value.unumber, MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL); |
| |
| for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++) |
| { |
| /* before every db segment, NULL the current entry */ |
| p_current_entry = NULL; |
| |
| /* get first */ |
| p_current_entry = _mac_util_db_flow_get_next_w_gem (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry); |
| while (NULL != p_current_entry) |
| { |
| printf("\n------------------------------\n"); |
| printf ("\nflow_id = %d flow_type = %d\n", p_current_entry->bal_flow_key.flow_id, p_current_entry->bal_flow_key.flow_type); |
| printf ("\n if_id = %d sub_term_id = %d svc_port_id = %d agg_id = %d vlan_id = %d\n", |
| p_current_entry->if_id, p_current_entry->sub_term_id, p_current_entry->svc_port_id, p_current_entry->agg_id, p_current_entry->vlan_id); |
| printf("\n is_waiting_for_svc_port_active = %s is_configuration_completed=%s ind_sent = %d\n", |
| p_current_entry->is_waiting_for_svc_port_active==BCMOS_TRUE ? "true" : "false", |
| p_current_entry->is_configuration_completed==BCMOS_TRUE ? "true" : "false", |
| p_current_entry->ind_sent); |
| printf("\n------------------------------\n"); |
| |
| /* get next */ |
| p_current_entry = _mac_util_db_flow_get_next_w_gem (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry); |
| } |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| |
| static bcmos_errno _cmd_flows_print_for_alloc_id(bcmcli_session *sess, const bcmcli_cmd_parm parm[], uint16_t nParms) |
| { |
| flow_list_entry *p_current_entry = NULL; |
| void *p_rsc_mgr_curr_entry = NULL; |
| void *p_rsc_mgr_next_entry = NULL; |
| |
| uint32_t if_id = 0; |
| |
| printf("Flow DB for a Alloc Id [%ld]: starting flow id=%d, max flow id=%d\n", |
| parm[0].value.unumber, MAC_UTIL_FLOW_DB_FLOW_ID_START_VAL, MAC_UTIL_FLOW_DB_FLOW_ID_MAX_VAL); |
| |
| for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++) |
| { |
| /* before every db segment, NULL the current entry */ |
| p_current_entry = NULL; |
| |
| /* get first */ |
| p_current_entry = _mac_util_db_flow_get_next_w_alloc_id (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry); |
| while (NULL != p_current_entry) |
| { |
| printf("\n------------------------------\n"); |
| printf ("\nflow_id = %d flow_type = %d\n", p_current_entry->bal_flow_key.flow_id, p_current_entry->bal_flow_key.flow_type); |
| printf ("\n if_id = %d sub_term_id = %d svc_port_id = %d agg_id = %d vlan_id = %d\n", |
| p_current_entry->if_id, p_current_entry->sub_term_id, p_current_entry->svc_port_id, p_current_entry->agg_id, p_current_entry->vlan_id); |
| printf("\n is_waiting_for_svc_port_active = %s is_configuration_completed=%s ind_sent = %d\n", |
| p_current_entry->is_waiting_for_svc_port_active==BCMOS_TRUE ? "true" : "false", |
| p_current_entry->is_configuration_completed==BCMOS_TRUE ? "true" : "false", |
| p_current_entry->ind_sent); |
| printf("\n------------------------------\n"); |
| |
| /* get next */ |
| p_current_entry = _mac_util_db_flow_get_next_w_alloc_id (if_id, parm[0].value.unumber, &p_rsc_mgr_curr_entry, &p_rsc_mgr_next_entry); |
| } |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| |
| /* Update CLI based on the system mode */ |
| static void handle_system_mode_change(bcmolt_devid dev) |
| { |
| if (dev == current_device) |
| { |
| bcmcli_entry *cur_dir = bcmcli_dir_get(current_session); |
| char old_dir_name[32] = ""; |
| |
| if (cur_dir) |
| strncpy(old_dir_name, bcmcli_token_name(cur_dir), sizeof(old_dir_name) - 1); |
| |
| bcmcli_dir_set(current_session, maple_dir); |
| api_cli_set_commands(current_session); |
| |
| /* Restore current CLI directory */ |
| cur_dir = bcmcli_dir_find(NULL, old_dir_name); |
| bcmcli_dir_set(current_session, cur_dir); |
| } |
| } |
| |
| |
| /*****************************************************************************/ |
| /** |
| * @brief mac_util_cli_init |
| * |
| * This routine is called from main to initialize the mac_app cli, |
| *that is used for internal unit testing. |
| * |
| * @param cli_dir - a pointer to the cli directory to init that cli in |
| * @return bcmos_errno |
| */ |
| /*****************************************************************************/ |
| bcmos_errno mac_util_cli_init(bcmcli_entry *cli_dir) |
| { |
| bcmcli_entry *p_cli_dir; |
| bcmos_errno rc = BCM_ERR_OK; |
| |
| do |
| { |
| p_cli_dir = bcmcli_dir_add(cli_dir, "Mac_Util", "Mac Util (debug)", BCMCLI_ACCESS_ADMIN, NULL); |
| |
| BCMCLI_MAKE_CMD_NOPARM(p_cli_dir, "print_flows", "print mac app flows list", _cmd_flows_print); |
| BCMCLI_MAKE_CMD(p_cli_dir, "print_flows_for_gem", "print mac flows sharing a GEM port", _cmd_flows_print_for_gem, |
| BCMCLI_MAKE_PARM("gem_port_id", "GEM Port Id", BCMCLI_PARM_UNUMBER, 0)); |
| BCMCLI_MAKE_CMD(p_cli_dir, "print_flows_for_alloc_id", "print mac flows sharing an Alloc Id", _cmd_flows_print_for_alloc_id, |
| BCMCLI_MAKE_PARM("alloc_id", "Alloc Id", BCMCLI_PARM_UNUMBER, 0)); |
| |
| /* Initialize the bal api cli UI */ |
| maple_dir = bcmcli_dir_add(NULL, "maple", "Maple API access", BCMCLI_ACCESS_ADMIN, NULL); |
| |
| sm_change_cb = handle_system_mode_change; |
| |
| /* Init device selector */ |
| rc = bcmolt_dev_sel_init(maple_dir); |
| |
| /* Add Maple API commands */ |
| rc = rc ? rc : api_cli_init(maple_dir, current_session); |
| |
| #ifdef BOARD |
| rc = rc ? rc : bcm_board_init(); |
| rc = rc ? rc : bcm_board_cli_init(NULL); |
| #endif |
| rc = rc ? rc : bcmtr_init(); |
| rc = rc ? rc : bcmtr_cld_cli_init(); |
| rc = rc ? rc : bcmtr_cli_init(); |
| |
| } while(0); |
| |
| return rc; |
| |
| return BCM_ERR_OK; |
| } |
| |
| /*****************************************************************************/ |
| /** |
| * @brief Un-initialize the mac util internal data structures |
| * |
| * @returns bcmos_errno == BCM_ERR_OK |
| * |
| * @note this routine does not seem to be used currently |
| *****************************************************************************/ |
| bcmos_errno mac_util_finish(void) |
| { |
| flow_list_entry *p_current_entry = NULL, *p_next_entry = NULL; |
| uint32_t if_id = 0; |
| |
| for (if_id=0; if_id < NUM_SUPPORTED_SUBSCRIBER_INTERFACES; if_id++) |
| { |
| /* before every db segment, NULL the current entry */ |
| p_current_entry = NULL; |
| p_next_entry = NULL; |
| |
| /* Free all the entries on the flows list */ |
| /* get first */ |
| p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry); |
| while (NULL != p_current_entry) |
| { |
| /* Remove it from the list, and free memory */ |
| _mac_util_db_flow_remove (if_id, p_current_entry); |
| _mac_util_db_flow_free (if_id, p_current_entry); |
| |
| /* get next */ |
| p_current_entry = _mac_util_db_flow_get_next_w_flow_key (if_id, p_current_entry, &p_next_entry); |
| } |
| } |
| |
| return BCM_ERR_OK; |
| } |
| |
| |
| bcmos_errno mac_util_access_terminal_sw_version_validate(bcmolt_devid device) |
| { |
| bcmolt_device_cfg cfg = {}; |
| bcmolt_device_key key = {}; |
| bcmos_errno rc; |
| |
| BCMOLT_CFG_INIT(&cfg, device, key); |
| BCMOLT_CFG_PROP_GET(&cfg, device, host_sw_version); |
| rc = bcmolt_cfg_get(device, &cfg.hdr); |
| if (rc != BCM_ERR_OK) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, "Unable to get OLT SW version\n"); |
| return rc; |
| } |
| |
| BCM_LOG(INFO, log_id_mac_util, |
| "Actual OLT SW version %d.%d.%X (Object model revision %d)\n", |
| cfg.data.host_sw_version.major, |
| cfg.data.host_sw_version.minor, |
| cfg.data.host_sw_version.revision, |
| cfg.data.host_sw_version.model); |
| |
| BCM_LOG(INFO, log_id_mac_util, |
| "BAL OLT SW version %d.%d.%X (Object model revision %d)\n", |
| BCMOLT_HOST_MAJOR_VER, |
| BCMOLT_HOST_MINOR_VER, |
| BCMOLT_HOST_REVISION_VER, |
| BCMOLT_MODEL_REVISION); |
| |
| /* Check for versions mismatch */ |
| if (cfg.data.host_sw_version.major != BCMOLT_HOST_MAJOR_VER || |
| cfg.data.host_sw_version.minor != BCMOLT_HOST_MINOR_VER || |
| cfg.data.host_sw_version.revision != BCMOLT_HOST_REVISION_VER || |
| cfg.data.host_sw_version.model != BCMOLT_MODEL_REVISION) |
| { |
| BCM_LOG(ERROR, log_id_mac_util, INBOLD_BAD( |
| "SW versions mismatch: BAL was complied with OTL SW version %d.%d.%X (Object model revision %d), " |
| "while actual OLT SW version is %d.%d.%X (Object model revision %d)\n"), |
| BCMOLT_HOST_MAJOR_VER, |
| BCMOLT_HOST_MINOR_VER, |
| BCMOLT_HOST_REVISION_VER, |
| BCMOLT_MODEL_REVISION, |
| cfg.data.host_sw_version.major, |
| cfg.data.host_sw_version.minor, |
| cfg.data.host_sw_version.revision, |
| cfg.data.host_sw_version.model); |
| return BCM_ERR_STATE; |
| } |
| return BCM_ERR_OK; |
| } |
| |
| |
| /*@}*/ |