| /* |
| Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. |
| |
| Redistribution and use in source and binary forms, with or without |
| modification, are permitted provided that the following conditions are |
| met: |
| * Redistributions of source code must retain the above copyright |
| notice, this list of conditions and the following disclaimer. |
| * Redistributions in binary form must reproduce the above |
| copyright notice, this list of conditions and the following |
| disclaimer in the documentation and/or other materials provided |
| with the distribution. |
| * Neither the name of The Linux Foundation nor the names of its |
| contributors may be used to endorse or promote products derived |
| from this software without specific prior written permission. |
| |
| THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED |
| WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT |
| ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS |
| BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
| CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
| SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR |
| BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN |
| IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| /*! |
| @file |
| IPACM_IfaceManager.cpp |
| |
| @brief |
| This file implements the IPAM iface_manager functionality. |
| |
| @Author |
| Skylar Chang |
| |
| */ |
| #include <string.h> |
| #include <sys/ioctl.h> |
| |
| #include <IPACM_IfaceManager.h> |
| #include <IPACM_EvtDispatcher.h> |
| #include <IPACM_Defs.h> |
| #include <IPACM_Wlan.h> |
| #include <IPACM_Lan.h> |
| #include <IPACM_Wan.h> |
| #include <IPACM_Iface.h> |
| #include <IPACM_Log.h> |
| |
| iface_instances *IPACM_IfaceManager::head = NULL; |
| |
| IPACM_IfaceManager::IPACM_IfaceManager() |
| { |
| IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, this); // register for IPA_CFG_CHANGE event |
| IPACM_EvtDispatcher::registr(IPA_LINK_UP_EVENT, this); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_AP_LINK_UP_EVENT, this); // register for wlan AP-iface |
| IPACM_EvtDispatcher::registr(IPA_WLAN_STA_LINK_UP_EVENT, this); // register for wlan STA-iface |
| #ifndef FEATURE_IPA_ANDROID |
| /* only MDM targets support device on bridge mode */ |
| IPACM_EvtDispatcher::registr(IPA_BRIDGE_LINK_UP_EVENT, this); // register for IPA_BRIDGE_LINK_UP_EVENT event |
| #endif /* not defined(FEATURE_IPA_ANDROID)*/ |
| IPACM_EvtDispatcher::registr(IPA_USB_LINK_UP_EVENT, this); // register for USB-iface |
| IPACM_EvtDispatcher::registr(IPA_WAN_EMBMS_LINK_UP_EVENT, this); // register for wan eMBMS-iface |
| return; |
| } |
| |
| void IPACM_IfaceManager::event_callback(ipa_cm_event_id event, void *param) |
| { |
| int ipa_interface_index; |
| ipacm_event_data_fid *evt_data = (ipacm_event_data_fid *)param; |
| ipacm_event_data_mac *StaData = (ipacm_event_data_mac *)param; |
| ipacm_event_data_all *data_all = (ipacm_event_data_all *)param; |
| ipacm_ifacemgr_data ifmgr_data; |
| |
| memset(&ifmgr_data,0,sizeof(ifmgr_data)); |
| |
| switch(event) |
| { |
| case IPA_CFG_CHANGE_EVENT: |
| IPACMDBG_H(" RESET IPACM_cfg \n"); |
| IPACM_Iface::ipacmcfg->Init(); |
| break; |
| case IPA_BRIDGE_LINK_UP_EVENT: |
| IPACMDBG_H(" Save the bridge0 mac info in IPACM_cfg \n"); |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data_all->if_index); |
| /* check for failure return */ |
| if (IPACM_FAILURE == ipa_interface_index) { |
| IPACMERR("IPA_BRIDGE_LINK_UP_EVENT: not supported iface id: %d\n", data_all->if_index); |
| break; |
| } |
| /* check if iface is bridge interface*/ |
| if (strcmp(IPACM_Iface::ipacmcfg->ipa_virtual_iface_name, IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name) == 0) |
| { |
| IPACM_Iface::ipacmcfg->ipa_bridge_enable = true; |
| memcpy(IPACM_Iface::ipacmcfg->bridge_mac, |
| data_all->mac_addr, |
| sizeof(IPACM_Iface::ipacmcfg->bridge_mac)); |
| IPACMDBG_H("cached bridge0 MAC %02x:%02x:%02x:%02x:%02x:%02x\n", |
| IPACM_Iface::ipacmcfg->bridge_mac[0], IPACM_Iface::ipacmcfg->bridge_mac[1], IPACM_Iface::ipacmcfg->bridge_mac[2], |
| IPACM_Iface::ipacmcfg->bridge_mac[3], IPACM_Iface::ipacmcfg->bridge_mac[4], IPACM_Iface::ipacmcfg->bridge_mac[5]); |
| } |
| break; |
| case IPA_LINK_UP_EVENT: |
| IPACMDBG_H("Recieved IPA_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); |
| /* check for failure return */ |
| if (IPACM_FAILURE == ipa_interface_index) { |
| IPACMERR("IPA_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); |
| break; |
| } |
| /* LTE-backhaul */ |
| if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == EMBMS_IF) |
| { |
| IPACMDBG("WAN-EMBMS (%s) link already up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); |
| } |
| else if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) |
| { |
| IPACMDBG_H("WAN-LTE (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); |
| ifmgr_data.if_index = evt_data->if_index; |
| ifmgr_data.if_type = Q6_WAN; |
| create_iface_instance(&ifmgr_data); |
| } |
| break; |
| |
| case IPA_USB_LINK_UP_EVENT: |
| IPACMDBG_H("Recieved IPA_USB_LINK_UP_EVENT event: link up %d: \n", evt_data->if_index); |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); |
| /* check for failure return */ |
| if (IPACM_FAILURE == ipa_interface_index) { |
| IPACMERR("IPA_USB_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); |
| break; |
| } |
| /* check if it's WAN_IF */ |
| if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) |
| { |
| /* usb-backhaul using sta_mode ECM_WAN*/ |
| IPACMDBG_H("WAN-usb (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, evt_data->if_index); |
| ifmgr_data.if_index = evt_data->if_index; |
| ifmgr_data.if_type = ECM_WAN; |
| create_iface_instance(&ifmgr_data); |
| } |
| else |
| { |
| ifmgr_data.if_index = evt_data->if_index; |
| ifmgr_data.if_type = Q6_WAN; |
| create_iface_instance(&ifmgr_data); |
| } |
| break; |
| |
| case IPA_WLAN_AP_LINK_UP_EVENT: |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); |
| /* check for failure return */ |
| if (IPACM_FAILURE == ipa_interface_index) { |
| IPACMERR("IPA_WLAN_AP_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); |
| break; |
| } |
| /* change iface category from unknown to WLAN_IF */ |
| if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) |
| { |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WLAN_IF; |
| IPACMDBG_H("WLAN AP (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); |
| ifmgr_data.if_index = evt_data->if_index; |
| ifmgr_data.if_type = Q6_WAN; |
| create_iface_instance(&ifmgr_data); |
| } |
| else |
| { |
| IPACMDBG_H("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); |
| } |
| break; |
| |
| case IPA_WLAN_STA_LINK_UP_EVENT: |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(StaData->if_index); |
| /* check for failure return */ |
| if (IPACM_FAILURE == ipa_interface_index) { |
| IPACMERR("IPA_WLAN_STA_LINK_UP_EVENT: not supported iface id: %d\n", StaData->if_index); |
| break; |
| } |
| /* change iface category from unknown to WAN_IF */ |
| if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == UNKNOWN_IF) |
| { |
| /* wlan-backhaul using sta_mode WLAN_WAN */ |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = WAN_IF; |
| IPACMDBG_H("WLAN STA (%s) link up, iface: %d: \n", |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, StaData->if_index); |
| |
| ifmgr_data.if_index = StaData->if_index; |
| ifmgr_data.if_type = WLAN_WAN; |
| memcpy(ifmgr_data.mac_addr, StaData->mac_addr, sizeof(ifmgr_data.mac_addr)); |
| create_iface_instance(&ifmgr_data); |
| } |
| else |
| { |
| IPACMDBG_H("iface %s already up and act as %d mode: \n", |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); |
| } |
| break; |
| |
| /* Add new instance open for eMBMS iface and wan iface */ |
| case IPA_WAN_EMBMS_LINK_UP_EVENT: |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(evt_data->if_index); |
| /* check for failure return */ |
| if (IPACM_FAILURE == ipa_interface_index) { |
| IPACMERR("IPA_WAN_EMBMS_LINK_UP_EVENT: not supported iface id: %d\n", evt_data->if_index); |
| break; |
| } |
| /* change iface category from unknown to EMBMS_IF */ |
| if ((IPACM_Iface::ipacmcfg->ipacm_odu_enable == true) && (IPACM_Iface::ipacmcfg->ipacm_odu_embms_enable == true)) |
| { |
| IPACMDBG(" ODU-mode enable or not (%d) \n",IPACM_Iface::ipacmcfg->ipacm_odu_enable); |
| if(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat == WAN_IF) |
| { |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat=EMBMS_IF; |
| IPACMDBG("WAN eMBMS (%s) link up, iface: %d: \n", IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,evt_data->if_index); |
| ifmgr_data.if_index = StaData->if_index; |
| ifmgr_data.if_type = Q6_WAN; |
| create_iface_instance(&ifmgr_data); |
| } |
| else |
| { |
| IPACMDBG("iface %s already up and act as %d mode: \n",IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); |
| } |
| } |
| break; |
| |
| default: |
| break; |
| } |
| return; |
| } |
| |
| int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) |
| { |
| int if_index = param->if_index; |
| ipacm_wan_iface_type is_sta_mode = param->if_type; |
| |
| int ipa_interface_index; |
| ipa_interface_index = IPACM_Iface::iface_ipa_index_query(if_index); |
| |
| if(ipa_interface_index == INVALID_IFACE) |
| { |
| IPACMDBG_H("Unhandled interface received, fid: %d\n",if_index); |
| return IPACM_SUCCESS; |
| } |
| |
| /* check if duplicate instance*/ |
| if(SearchInstance(ipa_interface_index) == IPA_INSTANCE_NOT_FOUND) |
| { |
| /* IPA_INSTANCE_NOT_FOUND */ |
| switch(IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat) |
| { |
| |
| case LAN_IF: |
| { |
| IPACMDBG_H("Creating Lan interface\n"); |
| IPACM_Lan *lan = new IPACM_Lan(ipa_interface_index); |
| if (lan->rx_prop == NULL && lan->tx_prop == NULL) |
| { |
| /* close the netdev instance if IPA not support*/ |
| lan->delete_iface(); |
| return IPACM_FAILURE; |
| } |
| IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, lan); |
| //IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, lan); |
| //IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, lan); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, lan); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, lan); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, lan); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, lan); |
| #ifdef FEATURE_IPA_ANDROID |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_TETHER, lan); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, lan); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, lan); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, lan); |
| #ifdef FEATURE_IPACM_HAL |
| IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_ADD, lan); |
| IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_DEL, lan); |
| #endif |
| #else |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, lan); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, lan); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, lan); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, lan); |
| #endif |
| IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, lan); // register for IPA_CFG_CHANGE event |
| IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, lan); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event |
| #ifdef FEATURE_IPA_ANDROID |
| IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, lan); |
| #endif |
| IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, lan); |
| #ifdef IPA_MTU_EVENT_MAX |
| IPACM_EvtDispatcher::registr(IPA_MTU_UPDATE, lan); |
| #endif |
| IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, lan); |
| /* IPA_LAN_DELETE_SELF should be always last */ |
| IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, lan); |
| IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", lan->dev_name, lan->ipa_if_num); |
| registr(ipa_interface_index, lan); |
| /* solve the new_addr comes earlier issue */ |
| IPACM_Iface::iface_addr_query(if_index); |
| } |
| break; |
| |
| case ETH_IF: |
| { |
| IPACMDBG_H("Creating ETH interface in router mode\n"); |
| IPACM_Lan *ETH = new IPACM_Lan(ipa_interface_index); |
| IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, ETH); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, ETH); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, ETH); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, ETH); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, ETH); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, ETH); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, ETH); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, ETH); |
| IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, ETH); |
| IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, ETH); |
| /* IPA_LAN_DELETE_SELF should be always last */ |
| IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, ETH); |
| IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", ETH->dev_name, ETH->ipa_if_num); |
| registr(ipa_interface_index, ETH); |
| /* solve the new_addr comes earlier issue */ |
| IPACM_Iface::iface_addr_query(if_index); |
| } |
| break; |
| |
| case ODU_IF: |
| { |
| if(IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true) |
| { |
| IPACMDBG_H("Creating ODU interface in router mode\n"); |
| IPACM_Lan *odu = new IPACM_Lan(ipa_interface_index); |
| IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, odu); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, odu); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_DEL_EVENT, odu); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, odu); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, odu); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, odu); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, odu); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, odu); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, odu); |
| IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, odu); |
| IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu); |
| /* IPA_LAN_DELETE_SELF should be always last */ |
| IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu); |
| IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); |
| registr(ipa_interface_index, odu); |
| /* solve the new_addr comes earlier issue */ |
| IPACM_Iface::iface_addr_query(if_index); |
| } |
| else |
| { |
| IPACMDBG_H("Creating ODU interface in bridge mode\n"); |
| IPACM_Lan *odu = new IPACM_Lan(ipa_interface_index); |
| IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, odu); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, odu); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, odu); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, odu); |
| IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, odu); |
| /* IPA_LAN_DELETE_SELF should be always last */ |
| IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, odu); |
| IPACMDBG_H("ipa_LAN (%s):ipa_index (%d) instance open/registr ok\n", odu->dev_name, odu->ipa_if_num); |
| registr(ipa_interface_index, odu); |
| /* solve the new_addr comes earlier issue */ |
| IPACM_Iface::iface_addr_query(if_index); |
| } |
| } |
| break; |
| |
| case WLAN_IF: |
| { |
| IPACMDBG_H("Creating WLan interface\n"); |
| IPACM_Wlan *wl = new IPACM_Wlan(ipa_interface_index); |
| if (wl->rx_prop == NULL && wl->tx_prop == NULL) |
| { |
| /* reset the AP-iface category to unknown */ |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = UNKNOWN_IF; |
| /* close the netdev instance if IPA not support*/ |
| wl->delete_iface(); |
| return IPACM_FAILURE; |
| } |
| IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_ADD_EVENT_EX, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_DEL_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_POWER_SAVE_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_CLIENT_RECOVER_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, wl); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, wl); |
| #ifdef FEATURE_IPA_ANDROID |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_TETHER, wl); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, wl); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, wl); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, wl); |
| #ifdef FEATURE_IPACM_HAL |
| IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_ADD, wl); |
| IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_DEL, wl); |
| IPACM_EvtDispatcher::registr(IPA_SSR_NOTICE, wl); |
| #endif |
| #else |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, wl); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, wl); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN, wl); |
| IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6, wl); |
| #endif |
| IPACM_EvtDispatcher::registr(IPA_PRIVATE_SUBNET_CHANGE_EVENT, wl); // register for IPA_PRIVATE_SUBNET_CHANGE_EVENT event |
| if (IPACM_Iface::ipacmcfg->isEthBridgingSupported()) |
| IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, wl); |
| IPACM_EvtDispatcher::registr(IPA_CRADLE_WAN_MODE_SWITCH, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, wl); |
| #ifndef FEATURE_IPA_ANDROID |
| IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_SCC, wl); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, wl); |
| #else |
| IPACM_EvtDispatcher::registr(IPA_TETHERING_STATS_UPDATE_EVENT, wl); |
| #endif |
| #ifdef FEATURE_IPACM_HAL |
| IPACM_EvtDispatcher::registr(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE, wl); |
| #endif |
| IPACM_EvtDispatcher::registr(IPA_WIGIG_CLIENT_ADD_EVENT, wl); |
| #ifdef IPA_MTU_EVENT_MAX |
| IPACM_EvtDispatcher::registr(IPA_MTU_UPDATE, wl); |
| #endif |
| /* IPA_LAN_DELETE_SELF should be always last */ |
| IPACM_EvtDispatcher::registr(IPA_LAN_DELETE_SELF, wl); |
| IPACMDBG_H("ipa_WLAN (%s):ipa_index (%d) instance open/registr ok\n", wl->dev_name, wl->ipa_if_num); |
| registr(ipa_interface_index, wl); |
| /* solve the new_addr comes earlier issue */ |
| IPACM_Iface::iface_addr_query(if_index); |
| } |
| break; |
| |
| case WAN_IF: |
| { |
| if((IPACM_Iface::ipacmcfg->ipacm_odu_enable == false) || (IPACM_Iface::ipacmcfg->ipacm_odu_router_mode == true)) |
| { |
| IPACMDBG_H("Creating Wan interface\n"); |
| IPACM_Wan *w; |
| if(is_sta_mode == WLAN_WAN) |
| { |
| w = new IPACM_Wan(ipa_interface_index, is_sta_mode, param->mac_addr); |
| if (w->rx_prop == NULL && w->tx_prop == NULL) |
| { |
| /* reset the AP-iface category to unknown */ |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat = UNKNOWN_IF; |
| /* close the netdev instance if IPA not support*/ |
| w->delete_iface(); |
| return IPACM_FAILURE; |
| } |
| } |
| else |
| { |
| w = new IPACM_Wan(ipa_interface_index, is_sta_mode, NULL); |
| if (w->rx_prop == NULL && w->tx_prop == NULL) |
| { |
| /* close the netdev instance if IPA not support*/ |
| w->delete_iface(); |
| return IPACM_FAILURE; |
| } |
| } |
| IPACM_EvtDispatcher::registr(IPA_ADDR_ADD_EVENT, w); |
| #ifdef FEATURE_IPA_ANDROID |
| IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, w); |
| IPACM_EvtDispatcher::registr(IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, w); |
| if(is_sta_mode == Q6_WAN) |
| { |
| IPACM_EvtDispatcher::registr(IPA_NETWORK_STATS_UPDATE_EVENT, w); |
| #ifdef IPA_MTU_EVENT_MAX |
| IPACM_EvtDispatcher::registr(IPA_MTU_SET, w); |
| #endif |
| }; |
| #else/* defined(FEATURE_IPA_ANDROID) */ |
| IPACM_EvtDispatcher::registr(IPA_ROUTE_ADD_EVENT, w); |
| IPACM_EvtDispatcher::registr(IPA_ROUTE_DEL_EVENT, w); |
| #endif /* not defined(FEATURE_IPA_ANDROID)*/ |
| IPACM_EvtDispatcher::registr(IPA_FIREWALL_CHANGE_EVENT, w); |
| IPACM_EvtDispatcher::registr(IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT, w); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_ENABLE, w); |
| IPACM_EvtDispatcher::registr(IPA_SW_ROUTING_DISABLE, w); |
| IPACM_EvtDispatcher::registr(IPA_CFG_CHANGE_EVENT, w); // register for IPA_CFG_CHANGE event |
| IPACM_EvtDispatcher::registr(IPA_WAN_XLAT_CONNECT_EVENT, w); |
| if(is_sta_mode == WLAN_WAN) |
| { |
| IPACM_EvtDispatcher::registr(IPA_WLAN_LINK_DOWN_EVENT, w); // for STA mode |
| #ifndef FEATURE_IPA_ANDROID |
| IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_SCC, w); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_SWITCH_TO_MCC, w); |
| #ifdef FEATURE_IPACM_HAL |
| IPACM_EvtDispatcher::registr(IPA_SSR_NOTICE, w); |
| IPACM_EvtDispatcher::registr(IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE, w); |
| #endif |
| #endif |
| } |
| else |
| { |
| IPACM_EvtDispatcher::registr(IPA_COALESCE_NOTICE, w); |
| IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, w); |
| } |
| |
| IPACMDBG_H("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", w->dev_name, w->ipa_if_num); |
| registr(ipa_interface_index, w); |
| /* solve the new_addr comes earlier issue */ |
| IPACM_Iface::iface_addr_query(if_index); |
| } |
| } |
| break; |
| |
| /* WAN-eMBMS instance */ |
| case EMBMS_IF: |
| { |
| IPACMDBG("Creating Wan-eMBSM interface\n"); |
| IPACM_Wan *embms = new IPACM_Wan(ipa_interface_index, is_sta_mode, NULL); |
| IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, embms); |
| IPACMDBG("ipa_WAN (%s):ipa_index (%d) instance open/registr ok\n", embms->dev_name, embms->ipa_if_num); |
| registr(ipa_interface_index, embms); |
| } |
| break; |
| |
| default: |
| IPACMDBG_H("Unhandled interface category received iface name: %s, category: %d\n", |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name, |
| IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].if_cat); |
| return IPACM_SUCCESS; |
| } |
| } |
| return IPACM_SUCCESS; |
| } |
| |
| |
| int IPACM_IfaceManager::registr(int ipa_if_index, IPACM_Listener *obj) |
| { |
| iface_instances *tmp = head,*nw; |
| |
| nw = (iface_instances *)malloc(sizeof(iface_instances)); |
| if(nw != NULL) |
| { |
| nw->ipa_if_index = ipa_if_index; |
| nw->obj = obj; |
| nw->next = NULL; |
| } |
| else |
| { |
| return IPACM_FAILURE; |
| } |
| |
| if(head == NULL) |
| { |
| head = nw; |
| } |
| else |
| { |
| while(tmp->next) |
| { |
| tmp = tmp->next; |
| } |
| tmp->next = nw; |
| } |
| return IPACM_SUCCESS; |
| } |
| |
| int IPACM_IfaceManager::deregistr(IPACM_Listener *param) |
| { |
| iface_instances *tmp = head,*tmp1,*prev = head; |
| |
| while(tmp != NULL) |
| { |
| if(tmp->obj == param) |
| { |
| tmp1 = tmp; |
| if(tmp == head) |
| { |
| head = head->next; |
| } |
| else if(tmp->next == NULL) |
| { |
| prev->next = NULL; |
| } |
| else |
| { |
| prev->next = tmp->next; |
| } |
| |
| tmp = tmp->next; |
| free(tmp1); |
| } |
| else |
| { |
| prev = tmp; |
| tmp = tmp->next; |
| } |
| } |
| return IPACM_SUCCESS; |
| } |
| |
| |
| int IPACM_IfaceManager::SearchInstance(int ipa_if_index) |
| { |
| |
| iface_instances *tmp = head; |
| |
| while(tmp != NULL) |
| { |
| if(ipa_if_index == tmp->ipa_if_index) |
| { |
| IPACMDBG_H("Find existed iface-instance name: %s\n", |
| IPACM_Iface::ipacmcfg->iface_table[ipa_if_index].iface_name); |
| return IPA_INSTANCE_FOUND; |
| } |
| tmp = tmp->next; |
| } |
| |
| IPACMDBG_H("No existed iface-instance name: %s,\n", |
| IPACM_Iface::ipacmcfg->iface_table[ipa_if_index].iface_name); |
| |
| return IPA_INSTANCE_NOT_FOUND; |
| } |