diff options
author | Wilson Sung <wilsonsung@google.com> | 2021-06-24 10:59:22 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2021-06-24 10:59:22 +0000 |
commit | f59248c348cd383df795512cb3c4a22932676bad (patch) | |
tree | 7e1f9900341fe21990a095a8a64c5fa9d6b3dd41 | |
parent | a31011d1da2a0b670865becfc4f4846b9bfd5545 (diff) | |
parent | 39e2d762cc5273a7762361905273367e5655458d (diff) | |
download | ipacfg-mgr-f59248c348cd383df795512cb3c4a22932676bad.tar.gz |
Merge remote-tracking branch 'goog/qcom/release/LA.UM.9.1.C11.11.00.00.841.013' into sc-dev am: 39e2d762cc
Original change: https://googleplex-android-review.googlesource.com/c/platform/hardware/qcom/sm8150/data/ipacfg-mgr/+/14702477
Change-Id: If8e7edf2206a6d01d96b89a8e3f9c1396a282776
-rw-r--r-- | hal/inc/HAL.h | 2 | ||||
-rw-r--r-- | hal/src/HAL.cpp | 4 | ||||
-rw-r--r-- | ipacm/Android.bp | 1 | ||||
-rw-r--r-- | ipacm/inc/IPACM_ConntrackListener.h | 18 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Defs.h | 16 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Filtering.h | 2 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Iface.h | 4 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Lan.h | 2 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Wan.h | 39 | ||||
-rw-r--r-- | ipacm/src/IPACM_Config.cpp | 7 | ||||
-rw-r--r-- | ipacm/src/IPACM_ConntrackClient.cpp | 17 | ||||
-rw-r--r-- | ipacm/src/IPACM_ConntrackListener.cpp | 337 | ||||
-rw-r--r-- | ipacm/src/IPACM_Filtering.cpp | 44 | ||||
-rw-r--r-- | ipacm/src/IPACM_Iface.cpp | 55 | ||||
-rw-r--r-- | ipacm/src/IPACM_IfaceManager.cpp | 15 | ||||
-rw-r--r-- | ipacm/src/IPACM_Lan.cpp | 228 | ||||
-rw-r--r-- | ipacm/src/IPACM_LanToLan.cpp | 14 | ||||
-rw-r--r-- | ipacm/src/IPACM_Main.cpp | 49 | ||||
-rw-r--r-- | ipacm/src/IPACM_OffloadManager.cpp | 33 | ||||
-rw-r--r-- | ipacm/src/IPACM_Wan.cpp | 806 | ||||
-rw-r--r-- | ipacm/src/IPACM_Wlan.cpp | 48 | ||||
-rw-r--r-- | ipacm_vendor_product.mk | 11 |
22 files changed, 1291 insertions, 461 deletions
diff --git a/hal/inc/HAL.h b/hal/inc/HAL.h index 894438f..92ec135 100644 --- a/hal/inc/HAL.h +++ b/hal/inc/HAL.h @@ -123,7 +123,7 @@ public: * Yet, a major version update, would not be backwards compatible. This means that a 2.x HAL * could not linked into the same IPACM code base as a 1.x HAL. */ - static HAL* makeIPAHAL(int /* version */, IOffloadManager* /* mgr */); + static Return<::android::sp<HAL>> makeIPAHAL(int /* version */, IOffloadManager* /* mgr */); /* IOffloadConfig */ Return<void> setHandles( diff --git a/hal/src/HAL.cpp b/hal/src/HAL.cpp index 3f1a41f..f18767a 100644 --- a/hal/src/HAL.cpp +++ b/hal/src/HAL.cpp @@ -62,7 +62,7 @@ using ::std::vector; /* ------------------------------ PUBLIC ------------------------------------ */ -HAL* HAL::makeIPAHAL(int version, IOffloadManager* mgr) { +Return<::android::sp<HAL>> HAL::makeIPAHAL(int version, IOffloadManager* mgr) { android::hardware::ProcessState::initWithMmapSize((size_t)(2 * KERNEL_PAGE)); if (DBG) @@ -70,7 +70,7 @@ HAL* HAL::makeIPAHAL(int version, IOffloadManager* mgr) { (mgr != nullptr) ? "provided" : "null"); if (nullptr == mgr) return NULL; else if (version != 1) return NULL; - HAL* ret = new HAL(mgr); + ::android::sp<HAL> ret = new HAL(mgr); if (nullptr == ret) return NULL; configureRpcThreadpool(1, false); ret->registerAsSystemService("ipacm"); diff --git a/ipacm/Android.bp b/ipacm/Android.bp index 5afc37f..6662fce 100644 --- a/ipacm/Android.bp +++ b/ipacm/Android.bp @@ -16,6 +16,7 @@ cc_binary { header_libs: ["device_kernel_headers"], cflags: ["-DFEATURE_IPA_ANDROID"] + ["-DFEATURE_IPACM_RESTART"] + [ "-DFEATURE_IPACM_HAL", + "-DDEBUG", "-Wall", "-Werror", "-Wno-error=macro-redefined", diff --git a/ipacm/inc/IPACM_ConntrackListener.h b/ipacm/inc/IPACM_ConntrackListener.h index 24a2c72..2977af7 100644 --- a/ipacm/inc/IPACM_ConntrackListener.h +++ b/ipacm/inc/IPACM_ConntrackListener.h @@ -61,6 +61,13 @@ typedef struct _nat_entry_bundle }nat_entry_bundle; +typedef struct _ct_entry +{ + struct nf_conntrack *ct; + u_int8_t protocol; + enum nf_conntrack_msg_type type; +}ct_entry; + class IPACM_ConntrackListener : public IPACM_Listener { @@ -68,6 +75,7 @@ private: bool isCTReg; bool isNatThreadStart; bool WanUp; + bool isProcessCTDone; NatApp *nat_inst; int NatIfaceCnt; @@ -77,12 +85,14 @@ private: uint32_t nonnat_iface_ipv4_addr[MAX_IFACE_ADDRESS]; uint32_t sta_clnt_ipv4_addr[MAX_STA_CLNT_IFACES]; IPACM_Config *pConfig; + ct_entry *ct_entries; + ct_entry ct_cache[MAX_CONNTRACK_ENTRIES]; #ifdef CT_OPT IPACM_LanToLan *p_lan2lan; #endif void ProcessCTMessage(void *); - void ProcessTCPorUDPMsg(struct nf_conntrack *, + bool ProcessTCPorUDPMsg(struct nf_conntrack *, enum nf_conntrack_msg_type, u_int8_t); void TriggerWANUp(void *); void TriggerWANDown(uint32_t); @@ -104,6 +114,7 @@ public: char wan_ifname[IPA_IFACE_NAME_LEN]; uint32_t wan_ipaddr; ipacm_wan_iface_type backhaul_mode; + bool isReadCTDone; IPACM_ConntrackListener(); void event_callback(ipa_cm_event_id, void *data); inline bool isWanUp() @@ -116,6 +127,11 @@ public: void HandleSTAClientAddEvt(uint32_t); void HandleSTAClientDelEvt(uint32_t); int CreateConnTrackThreads(void); + void readConntrack(int fd); + void processConntrack(void); + void CacheORDeleteConntrack(struct nf_conntrack *ct, + enum nf_conntrack_msg_type type, u_int8_t protocol); + void processCacheConntrack(void); }; extern IPACM_ConntrackListener *CtList; diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h index a3cbba1..82e9c6b 100644 --- a/ipacm/inc/IPACM_Defs.h +++ b/ipacm/inc/IPACM_Defs.h @@ -105,6 +105,11 @@ extern "C" #define NUM_IPV6_PREFIX_FLT_RULE 1 #define NUM_IPV6_PREFIX_MTU_RULE 1 +#define MAX_CONNTRACK_ENTRIES 100 +#define CT_ENTRIES_BUFFER_SIZE 8096 +#define LOOPBACK_MASK 0xFF000000 +#define LOOPBACK_ADDR 0x7F000000 + /*--------------------------------------------------------------------------- Return values indicating error status ---------------------------------------------------------------------------*/ @@ -188,6 +193,10 @@ typedef enum IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, /* ipacm_event_eth_bridge*/ IPA_SSR_NOTICE, /* NULL*/ IPA_COALESCE_NOTICE, /* NULL*/ +#ifdef IPA_MTU_EVENT_MAX + IPA_MTU_SET, /* ipa_mtu_info */ + IPA_MTU_UPDATE, /* ipacm_event_mtu_info */ +#endif #ifdef FEATURE_L2TP IPA_ADD_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */ IPA_DEL_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */ @@ -402,4 +411,11 @@ typedef struct { _ipacm_offload_prefix prefix; } ipacm_event_ipahal_stream; +#ifdef IPA_MTU_EVENT_MAX +typedef struct _ipacm_event_mtu_info +{ + int if_index; + ipa_mtu_info mtu_info; +} ipacm_event_mtu_info; +#endif #endif /* IPA_CM_DEFS_H */ diff --git a/ipacm/inc/IPACM_Filtering.h b/ipacm/inc/IPACM_Filtering.h index 428c21a..6667235 100644 --- a/ipacm/inc/IPACM_Filtering.h +++ b/ipacm/inc/IPACM_Filtering.h @@ -48,6 +48,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <linux/rmnet_ipa_fd_ioctl.h> #define IPA_PCIE_MODEM_RULE_ID_START 69 +#define IPA_PCIE_MODEM_RULE_ID_MAX 1000 class IPACM_Filtering { @@ -80,6 +81,7 @@ private: int fd; /* File descriptor of the IPA device node /dev/ipa */ int total_num_offload_rules; int pcie_modem_rule_id; + bool pcie_modem_rule_id_in_use[IPA_PCIE_MODEM_RULE_ID_MAX]; }; #endif //IPACM_FILTERING_H diff --git a/ipacm/inc/IPACM_Iface.h b/ipacm/inc/IPACM_Iface.h index 55d9e99..35d12db 100644 --- a/ipacm/inc/IPACM_Iface.h +++ b/ipacm/inc/IPACM_Iface.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2020, 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 @@ -59,7 +59,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IPV4_DEFAULT_FILTERTING_RULES 3 #ifdef FEATURE_IPA_ANDROID -#define IPV6_DEFAULT_FILTERTING_RULES 8 +#define IPV6_DEFAULT_FILTERTING_RULES 5 #else #define IPV6_DEFAULT_FILTERTING_RULES 4 #endif diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h index 605edb5..de64be1 100644 --- a/ipacm/inc/IPACM_Lan.h +++ b/ipacm/inc/IPACM_Lan.h @@ -230,6 +230,8 @@ protected: int reset_to_dummy_flt_rule(ipa_ip_type iptype, uint32_t rule_hdl); + virtual int modify_ipv6_prefix_flt_rule(uint32_t* prefix); + virtual int install_ipv6_prefix_flt_rule(uint32_t* prefix); virtual void delete_ipv6_prefix_flt_rule(); diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h index 31949c5..9460938 100644 --- a/ipacm/inc/IPACM_Wan.h +++ b/ipacm/inc/IPACM_Wan.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2020, 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 @@ -53,7 +53,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV4 2 #ifdef FEATURE_IPA_ANDROID -#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 7 +#define IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6 4 #define IPA_V2_NUM_TCP_WAN_FILTER_RULE_IPV6 3 #define IPA_V2_NUM_MULTICAST_WAN_FILTER_RULE_IPV6 3 #define IPA_V2_NUM_FRAG_WAN_FILTER_RULE_IPV6 1 @@ -63,6 +63,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define NETWORK_STATS "%s %llu %llu %llu %llu" #define IPA_NETWORK_STATS_FILE_NAME "/data/misc/ipa/network_stats" +#define IPA_OFFLOAD_TETHER_STATE_FILE_NAME "/data/vendor/ipa/offload_state" typedef struct _wan_client_rt_hdl { @@ -105,8 +106,10 @@ public: static bool wan_up; static bool wan_up_v6; static uint8_t xlat_mux_id; - static uint16_t mtu_default_wan; - uint16_t mtu_size; + + static uint16_t mtu_default_wan_v4; + static uint16_t mtu_default_wan_v6; + /* IPACM interface name */ static char wan_up_dev_name[IF_NAME_LEN]; static uint32_t curr_wan_ip; @@ -145,15 +148,14 @@ public: { if (isWanUP(ipa_if_num_tether)) { - return mtu_default_wan; + return mtu_default_wan_v4; } } else if (iptype == IPA_IP_v6) { if (isWanUP_V6(ipa_if_num_tether)) { - return mtu_default_wan; - + return mtu_default_wan_v6; } } return DEFAULT_MTU_SIZE; @@ -405,6 +407,14 @@ private: /* handle for TCP RST rule */ uint32_t tcp_rst_hdl; + /* V4 MTU value. */ + uint16_t mtu_v4; + bool mtu_v4_set; + + /* V6 MTU value. */ + uint16_t mtu_v6; + bool mtu_v6_set; + inline ipa_wan_client* get_client_memptr(ipa_wan_client *param, int cnt) { char *ret = ((char *)param) + (wan_client_len * cnt); @@ -583,10 +593,13 @@ private: return IPACM_SUCCESS; } - int handle_wan_hdr_init(uint8_t *mac_addr); + int handle_wan_hdr_init(uint8_t *mac_addr, bool replaced = false, int entry = 0); int handle_wan_client_ipaddr(ipacm_event_data_all *data); int handle_wan_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptype); + /* handle_gw_mac_renew, index_client valiud is success */ + int handle_gw_mac_renew(ipacm_event_data_all *data, int index_client); + /* handle new_address event */ int handle_addr_evt(ipacm_event_data_addr *data); @@ -594,10 +607,10 @@ private: int handle_addr_evt_mhi_q6(ipacm_event_data_addr *data); /* wan default route/filter rule configuration */ - int handle_route_add_evt(ipa_ip_type iptype); + int handle_route_add_evt(ipa_ip_type iptype, bool add_only = false); /* construct complete STA ethernet header */ - int handle_sta_header_add_evt(); + int handle_sta_header_add_evt(bool renew = false); bool check_dft_firewall_rules_attr_mask(IPACM_firewall_conf_t *firewall_config); @@ -612,7 +625,7 @@ private: /* configure the initial firewall filter rules */ int config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4, ipa_ioc_add_flt_rule *pFilteringTable_v6); - int handle_route_del_evt(ipa_ip_type iptype); + int handle_route_del_evt(ipa_ip_type iptype, bool delete_only = false); int del_dft_firewall_rules(ipa_ip_type iptype); @@ -645,8 +658,6 @@ private: int add_dft_filtering_rule(struct ipa_flt_rule_add* rules, int rule_offset, ipa_ip_type iptype); - int add_tcpv6_filtering_rule(struct ipa_flt_rule_add* rules, int rule_offset); - int install_wan_filtering_rule(bool is_sw_routing); void handle_wlan_SCC_MCC_switch(bool, ipa_ip_type); @@ -676,7 +687,7 @@ private: int delete_tcp_fin_rst_exception_rule(); - /* Query mtu size */ + /* MTU helper functions */ int query_mtu_size(); }; diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp index c396c6c..d0c33e9 100644 --- a/ipacm/src/IPACM_Config.cpp +++ b/ipacm/src/IPACM_Config.cpp @@ -106,7 +106,12 @@ const char *ipacm_event_name[] = { __stringify(IPA_ETH_BRIDGE_CLIENT_ADD), /* ipacm_event_eth_bridge*/ __stringify(IPA_ETH_BRIDGE_CLIENT_DEL), /* ipacm_event_eth_bridge*/ __stringify(IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH), /* ipacm_event_eth_bridge*/ - __stringify(IPA_SSR_NOTICE) /* NULL*/ + __stringify(IPA_SSR_NOTICE), /* NULL*/ + __stringify(IPA_COALESCE_NOTICE), /* NULL*/ +#ifdef IPA_MTU_EVENT_MAX + __stringify(IPA_MTU_SET), /* ipa_mtu_info */ + __stringify(IPA_MTU_UPDATE), /* ipacm_event_mtu_info */ +#endif #ifdef FEATURE_L2TP __stringify(IPA_ADD_VLAN_IFACE), /* ipa_ioc_vlan_iface_info */ __stringify(IPA_DEL_VLAN_IFACE), /* ipa_ioc_vlan_iface_info */ diff --git a/ipacm/src/IPACM_ConntrackClient.cpp b/ipacm/src/IPACM_ConntrackClient.cpp index 8a2499c..29afd50 100644 --- a/ipacm/src/IPACM_ConntrackClient.cpp +++ b/ipacm/src/IPACM_ConntrackClient.cpp @@ -482,12 +482,18 @@ void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *) blocks waiting for events. */ IPACMDBG("Waiting for events\n"); +ctcatch: ret = nfct_catch(pClient->tcp_hdl); - if(ret == -1) + if((ret == -1) && (errno != ENOMSG)) { - IPACMERR("(%d)(%s)\n", ret, strerror(errno)); + IPACMERR("(%d)(%d)(%s)\n", ret, errno, strerror(errno)); return NULL; } + else + { + IPACMDBG("ctcatch ret:%d, errno:%d\n", ret, errno); + goto ctcatch; + } IPACMDBG("Exit from tcp thread\n"); @@ -568,14 +574,15 @@ void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *) /* Block to catch events from net filter connection track */ ctcatch: ret = nfct_catch(pClient->udp_hdl); - if(ret == -1) + /* Due to conntrack dump, sequence number might mismatch for initial events. */ + if((ret == -1) && (errno != ENOMSG) && (errno != EILSEQ)) { - IPACMDBG("(%d)(%s)\n", ret, strerror(errno)); + IPACMDBG("(%d)(%d)(%s)\n", ret, errno, strerror(errno)); return NULL; } else { - IPACMDBG("ctcatch ret:%d\n", ret); + IPACMDBG("ctcatch ret:%d, errno:%d\n", ret, errno); goto ctcatch; } diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp index e006393..fd1566d 100644 --- a/ipacm/src/IPACM_ConntrackListener.cpp +++ b/ipacm/src/IPACM_ConntrackListener.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2020, 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 @@ -35,19 +35,22 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_EvtDispatcher.h" #include "IPACM_Iface.h" #include "IPACM_Wan.h" +#pragma clang diagnostic ignored "-Wdeprecated-declarations" IPACM_ConntrackListener::IPACM_ConntrackListener() { IPACMDBG("\n"); - isNatThreadStart = false; isCTReg = false; WanUp = false; + isReadCTDone = false; + isProcessCTDone = false; nat_inst = NatApp::GetInstance(); NatIfaceCnt = 0; StaClntCnt = 0; pNatIfaces = NULL; + ct_entries = NULL; pConfig = IPACM_Config::GetInstance();; memset(nat_iface_ipv4_addr, 0, sizeof(nat_iface_ipv4_addr)); @@ -66,6 +69,9 @@ IPACM_ConntrackListener::IPACM_ConntrackListener() #ifdef CT_OPT p_lan2lan = IPACM_LanToLan::getLan2LanInstance(); #endif + + /* Initialize the CT cache. */ + memset(ct_cache, 0, sizeof(ct_cache)); } void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, @@ -97,6 +103,12 @@ void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt, IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); CreateConnTrackThreads(); TriggerWANUp(data); + if(isReadCTDone && !isProcessCTDone) + { + processConntrack(); + } + /* Process the cached entries. */ + processCacheConntrack(); break; case IPA_HANDLE_WAN_DOWN: @@ -667,6 +679,7 @@ void IPACM_ConntrackListener::ProcessCTMessage(void *param) { ipacm_ct_evt_data *evt_data = (ipacm_ct_evt_data *)param; u_int8_t l4proto = 0; + bool cache_ct = false; #ifdef IPACM_DEBUG char buf[1024]; @@ -688,11 +701,14 @@ void IPACM_ConntrackListener::ProcessCTMessage(void *param) } else { - ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto); + cache_ct = ProcessTCPorUDPMsg(evt_data->ct, evt_data->type, l4proto); } /* Cleanup item that was allocated during the original CT callback */ - nfct_destroy(evt_data->ct); + if (!cache_ct) + nfct_destroy(evt_data->ct); + else + CacheORDeleteConntrack(evt_data->ct, evt_data->type, l4proto); return; } @@ -839,7 +855,7 @@ void IPACM_ConntrackListener::AddORDeleteNatEntry(const nat_entry_bundle *input) } else if (IPPROTO_UDP == input->rule->protocol) { - if (NFCT_T_NEW == input->type) + if (NFCT_T_NEW == input->type || NFCT_T_UPDATE == input->type) { IPACMDBG("New UDP connection at time %ld\n", time(NULL)); if (!CtList->isWanUp()) @@ -872,6 +888,8 @@ void IPACM_ConntrackListener::PopulateTCPorUDPEntry( uint32_t status, nat_table_entry *rule) { + uint32_t repl_dst_ip; + if (IPS_DST_NAT == status) { IPACMDBG("Destination NAT\n"); @@ -956,6 +974,15 @@ void IPACM_ConntrackListener::PopulateTCPorUDPEntry( { IPACMDBG("unable to retrieve private port\n"); } + + /* If Reply destination IP is not Public IP, install dummy NAT rule. */ + repl_dst_ip = nfct_get_attr_u32(ct, ATTR_REPL_IPV4_DST); + repl_dst_ip = ntohl(repl_dst_ip); + if(repl_dst_ip != rule->public_ip) + { + IPACMDBG_H("Reply dst IP:0x%x not equal to wan ip:0x%x\n",repl_dst_ip, rule->public_ip); + rule->private_ip = rule->public_ip; + } } return; @@ -1029,7 +1056,7 @@ void IPACM_ConntrackListener::CheckSTAClient( } /* conntrack send in host order and ipa expects in host order */ -void IPACM_ConntrackListener::ProcessTCPorUDPMsg( +bool IPACM_ConntrackListener::ProcessTCPorUDPMsg( struct nf_conntrack *ct, enum nf_conntrack_msg_type type, u_int8_t l4proto) @@ -1038,6 +1065,7 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( uint32_t status = 0; uint32_t orig_src_ip, orig_dst_ip; bool isAdd = false; + bool cache_ct = false; nat_entry_bundle nat_entry; nat_entry.isTempEntry = false; @@ -1067,7 +1095,7 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( if(orig_src_ip == 0) { IPACMERR("unable to retrieve orig src ip address\n"); - return; + return cache_ct; } orig_dst_ip = nfct_get_attr_u32(ct, ATTR_ORIG_IPV4_DST); @@ -1075,7 +1103,7 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( if(orig_dst_ip == 0) { IPACMERR("unable to retrieve orig dst ip address\n"); - return; + return cache_ct; } if(orig_src_ip == wan_ipaddr) @@ -1096,13 +1124,16 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( #ifdef CT_OPT HandleLan2Lan(ct, type, &rule); #endif - IPACMDBG("Neither source Nor destination nat\n"); - goto IGNORE; + IPACMDBG("Neither source Nor destination nat.\n"); + /* If WAN is not up, cache the event. */ + if(!CtList->isWanUp()) + cache_ct = true; + goto IGNORE; } } - PopulateTCPorUDPEntry(ct, status, &rule); rule.public_ip = wan_ipaddr; + PopulateTCPorUDPEntry(ct, status, &rule); if (rule.private_ip != wan_ipaddr) { @@ -1129,7 +1160,7 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( CheckSTAClient(&rule, &nat_entry.isTempEntry); nat_entry.rule = &rule; AddORDeleteNatEntry(&nat_entry); - return; + return cache_ct; IGNORE: IPACMDBG_H("ignoring below Nat Entry\n"); @@ -1139,7 +1170,7 @@ IGNORE: IPACMDBG("private port or src port: 0x%x, Decimal:%d\n", rule.private_port, rule.private_port); IPACMDBG("public port or reply dst port: 0x%x, Decimal:%d\n", rule.public_port, rule.public_port); IPACMDBG("Protocol: %d, destination nat flag: %d\n", rule.protocol, rule.dst_nat); - return; + return cache_ct; } void IPACM_ConntrackListener::HandleSTAClientAddEvt(uint32_t clnt_ip_addr) @@ -1201,3 +1232,283 @@ void IPACM_ConntrackListener::HandleSTAClientDelEvt(uint32_t clnt_ip_addr) nat_inst->FlushTempEntries(clnt_ip_addr, false); return; } + +bool isLocalHostAddr(uint32_t src_ip_addr, uint32_t dst_ip_addr) { + + src_ip_addr = ntohl(src_ip_addr); + dst_ip_addr = ntohl(dst_ip_addr); + if ((src_ip_addr & LOOPBACK_MASK) == LOOPBACK_ADDR || (dst_ip_addr & LOOPBACK_MASK) == LOOPBACK_ADDR) /* (loopback) */ + return true; + return false; +} + +void IPACM_ConntrackListener::readConntrack(int fd) { + + int recv_bytes = -1, index = 0, len =0; + char buffer[CT_ENTRIES_BUFFER_SIZE]; + struct nf_conntrack *ct; + struct nlmsghdr *nl_header; + struct iovec iov = { + .iov_base = buffer, + .iov_len = CT_ENTRIES_BUFFER_SIZE, + }; + struct sockaddr_nl addr; + struct msghdr msg = { + .msg_name = &addr, + .msg_namelen = sizeof(struct sockaddr_nl), + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = NULL, + .msg_controllen = 0, + .msg_flags = 0, + }; + + len = MAX_CONNTRACK_ENTRIES * sizeof(ct_entry); + + ct_entries = (ct_entry *) malloc(len); + if(ct_entries == NULL) + { + IPACMERR("unable to allocate ct_entries memory \n"); + return; + } + memset(ct_entries, 0, len); + + if( fd < 0) + { + IPACMDBG_H("Invalid fd %d \n",fd); + free(ct_entries); + return; + } + IPACMDBG_H("receiving conntrack entries started.\n"); + len = CT_ENTRIES_BUFFER_SIZE; + while (len > 0) + { + memset(buffer, 0, CT_ENTRIES_BUFFER_SIZE); + recv_bytes = recvmsg(fd, &msg, 0); + if(recv_bytes < 0) + { + IPACMDBG_H("error in receiving conntrack entries %d%s\n",errno, strerror(errno)); + break; + } + else + { + len -= recv_bytes; + nl_header = (struct nlmsghdr *)buffer; + IPACMDBG_H("Number of bytes:%d to parse\n", recv_bytes); + while(NLMSG_OK(nl_header, recv_bytes) && (index < MAX_CONNTRACK_ENTRIES)) + { + if (nl_header->nlmsg_type == NLMSG_ERROR) + { + IPACMDBG_H("Error, recv_bytes is %d\n",recv_bytes); + break; + } + ct = nfct_new(); + if (ct != NULL) + { + int parseResult = nfct_parse_conntrack((nf_conntrack_msg_type) NFCT_T_ALL,nl_header, ct); + if(parseResult != NFCT_T_ERROR && parseResult != 0) + { + ct_entries[index].ct = ct; + ct_entries[index++].type = (nf_conntrack_msg_type)parseResult; + } + else + { + IPACMDBG_H("error in parsing %d%s \n", errno, strerror(errno)); + nfct_destroy(ct); + } + } + else + { + IPACMDBG_H("ct allocation failed\n"); + } + if (nl_header->nlmsg_type == NLMSG_DONE) + { + IPACMDBG_H("Message is done.\n"); + break; + } + nl_header = NLMSG_NEXT(nl_header, recv_bytes); + } + } + } + + isReadCTDone = true; + IPACMDBG_H("receiving conntrack entries ended. No of entries: %d\n", index); + if(isWanUp() && !isProcessCTDone) + { + IPACMDBG_H("wan is up, process ct entries \n"); + processConntrack(); + } + + return ; +} + +void IPACM_ConntrackListener::processConntrack() { + + uint8_t ip_type; + int index = 0; + ipacm_ct_evt_data *ct_data; + IPACMDBG_H("process conntrack started \n"); + if(ct_entries != NULL) + { + while(ct_entries[index].ct != NULL) + { + ip_type = nfct_get_attr_u8(ct_entries[index].ct, ATTR_REPL_L3PROTO); + if((AF_INET == ip_type) && isLocalHostAddr(nfct_get_attr_u32(ct_entries[index].ct, ATTR_ORIG_IPV4_SRC), + nfct_get_attr_u32(ct_entries[index].ct, ATTR_ORIG_IPV4_DST))) + { + IPACMDBG_H(" loopback entry \n"); + goto IGNORE; + } + +#ifndef CT_OPT + if(AF_INET6 == ip_type) + { + IPACMDBG("Ignoring ipv6(%d) connections\n", ip_type); + goto IGNORE; + } +#endif + + ct_data = (ipacm_ct_evt_data *)malloc(sizeof(ipacm_ct_evt_data)); + if(ct_data == NULL) + { + IPACMERR("unable to allocate memory \n"); + goto IGNORE; + } + + ct_data->ct = ct_entries[index].ct; + ct_data->type = ct_entries[index].type; + +#ifdef CT_OPT + if(AF_INET6 == ip_type) + { + ProcessCTV6Message(ct_data); + } +#else + ProcessCTMessage(ct_data); +#endif + index++; + free(ct_data); + continue; +IGNORE: + nfct_destroy(ct_entries[index].ct); + index++; + } + } + else + { + IPACMDBG_H("ct entry is null\n"); + return ; + } + isProcessCTDone = true; + free(ct_entries); + ct_entries = NULL; + IPACMDBG_H("process conntrack ended. Number of entries:%d \n", index); + return; +} + +void IPACM_ConntrackListener::CacheORDeleteConntrack +( + struct nf_conntrack *ct, + enum nf_conntrack_msg_type type, + u_int8_t protocol +) +{ + u_int8_t tcp_state; + int i = 0, free_idx = -1; + + IPACMDBG("CT entry, type (%d), protocol(%d)\n", type, protocol); + /* Check for duplicate entry and in parallel find first free index. */ + for(; i < MAX_CONNTRACK_ENTRIES; i++) + { + if (ct_cache[i].ct != NULL) + { + if (nfct_cmp(ct_cache[i].ct, ct, NFCT_CMP_ORIG | NFCT_CMP_REPL)) + { + /* Duplicate entry. */ + IPACMDBG("Duplicate CT entry, type (%d), protocol(%d)\n", + type, protocol); + break; + } + } + else if ((ct_cache[i].ct == NULL) && (free_idx == -1)) + { + /* Cache the first free index. */ + free_idx = i; + } + } + + /* Duplicate entry handling. */ + if (i < MAX_CONNTRACK_ENTRIES) + { + if (IPPROTO_TCP == protocol) + { + tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + if (TCP_CONNTRACK_FIN_WAIT == tcp_state || type == NFCT_T_DESTROY) + { + IPACMDBG("TCP state TCP_CONNTRACK_FIN_WAIT(%d) " + "or type NFCT_T_DESTROY\n", tcp_state); + nfct_destroy(ct_cache[i].ct); + nfct_destroy(ct); + memset(&ct_cache[i], 0, sizeof(ct_cache[i])); + return ; + } + } + if ((IPPROTO_UDP == protocol) && (type == NFCT_T_DESTROY)) + { + IPACMDBG("UDP type NFCT_T_DESTROY\n"); + nfct_destroy(ct_cache[i].ct); + nfct_destroy(ct); + memset(&ct_cache[i], 0, sizeof(ct_cache[i])); + return; + } + } + else if ((i == MAX_CONNTRACK_ENTRIES) && + (type != NFCT_T_DESTROY) && (free_idx != -1)) + { + if (IPPROTO_TCP == protocol) + { + tcp_state = nfct_get_attr_u8(ct, ATTR_TCP_STATE); + if (TCP_CONNTRACK_ESTABLISHED == tcp_state) + { + IPACMDBG("TCP state TCP_CONNTRACK_ESTABLISHED\n"); + /* Cache the entry. */ + ct_cache[free_idx].ct = ct; + ct_cache[free_idx].protocol = protocol; + ct_cache[free_idx].type = type; + return; + } + } + if (IPPROTO_UDP == protocol) + { + if (NFCT_T_NEW == type) + { + IPACMDBG("New UDP connection\n"); + /* Cache the entry. */ + ct_cache[free_idx].ct = ct; + ct_cache[free_idx].protocol = protocol; + ct_cache[free_idx].type = type; + return; + } + } + } + /* In all other cases, free the conntracy entry. */ + nfct_destroy(ct); + return ; +} +void IPACM_ConntrackListener::processCacheConntrack(void) +{ + int i = 0; + + IPACMDBG("Entry:\n"); + for(; i < MAX_CONNTRACK_ENTRIES; i++) + { + if (ct_cache[i].ct != NULL) + { + ProcessTCPorUDPMsg(ct_cache[i].ct, ct_cache[i].type, ct_cache[i].protocol); + nfct_destroy(ct_cache[i].ct); + memset(&ct_cache[i], 0, sizeof(ct_cache[i])); + } + } + IPACMDBG("Exit:\n"); +} + diff --git a/ipacm/src/IPACM_Filtering.cpp b/ipacm/src/IPACM_Filtering.cpp index 8aa25a6..875a794 100644 --- a/ipacm/src/IPACM_Filtering.cpp +++ b/ipacm/src/IPACM_Filtering.cpp @@ -60,6 +60,7 @@ IPACM_Filtering::IPACM_Filtering() } total_num_offload_rules = 0; pcie_modem_rule_id = 0; + memset(pcie_modem_rule_id_in_use, 0, sizeof(pcie_modem_rule_id_in_use)); } IPACM_Filtering::~IPACM_Filtering() @@ -710,7 +711,7 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r bool IPACM_Filtering::AddOffloadFilteringRule(struct ipa_ioc_add_flt_rule *flt_rule_tbl, uint8_t mux_id, uint8_t default_path) { #ifdef WAN_IOCTL_ADD_OFFLOAD_CONNECTION - int ret = 0, cnt, pos = 0; + int ret = 0, cnt, pos = 0, i; ipa_add_offload_connection_req_msg_v01 qmi_add_msg; int fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); if(fd_wwan_ioctl < 0) @@ -807,7 +808,23 @@ bool IPACM_Filtering::AddOffloadFilteringRule(struct ipa_ioc_add_flt_rule *flt_r sizeof(struct ipa_filter_rule_type_v01)); IPACMDBG_H("mux-id %d, hashable %d\n", qmi_add_msg.filter_spec_ex2_list[pos].mux_id, qmi_add_msg.filter_spec_ex2_list[pos].is_rule_hashable); pos++; - pcie_modem_rule_id = (pcie_modem_rule_id + 1)%100; + pcie_modem_rule_id_in_use[pcie_modem_rule_id] = true; + for(i = 0; i < IPA_PCIE_MODEM_RULE_ID_MAX; i++) + { + pcie_modem_rule_id = (pcie_modem_rule_id + 1)%IPA_PCIE_MODEM_RULE_ID_MAX; + if(!pcie_modem_rule_id_in_use[pcie_modem_rule_id]) + break; + } + + if(i == IPA_PCIE_MODEM_RULE_ID_MAX) + { + IPACMERR("all handles are in use, max = %d\n", i); + return false; + } + else + { + IPACMDBG("next free pcie_modem_rule_id: %d\n", pcie_modem_rule_id); + } } else { @@ -892,6 +909,12 @@ bool IPACM_Filtering::DelOffloadFilteringRule(struct ipa_ioc_del_flt_rule const /* passing rule-id to wan-driver */ qmi_del_msg.filter_handle_list[pos].filter_spec_identifier = flt_rule_tbl->hdl[cnt].hdl; pos++; + + /* set in use to false for future rule additions (need to subtract offset and mod max index) */ + pcie_modem_rule_id_in_use[(IPA_PCIE_MODEM_RULE_ID_MAX + flt_rule_tbl->hdl[cnt].hdl - IPA_PCIE_MODEM_RULE_ID_START) + % IPA_PCIE_MODEM_RULE_ID_MAX] = false; + IPACMDBG("freeing pcie_modem_rule_id: %d\n", (IPA_PCIE_MODEM_RULE_ID_MAX + flt_rule_tbl->hdl[cnt].hdl -IPA_PCIE_MODEM_RULE_ID_START) + % IPA_PCIE_MODEM_RULE_ID_MAX); } else { @@ -983,17 +1006,18 @@ bool IPACM_Filtering::ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTabl } ret = ioctl(fd, IPA_IOC_MDFY_FLT_RULE, ruleTable); - if (ret != 0) - { - IPACMERR("Failed modifying filtering rule %pK\n", ruleTable); - for (i = 0; i < ruleTable->num_rules; i++) + for (i = 0; i < ruleTable->num_rules; i++) + { + if (ruleTable->rules[i].status != 0) { - if (ruleTable->rules[i].status != 0) - { - IPACMERR("Modifying filter rule %d failed\n", i); - } + IPACMERR("Modifying filter rule %d failed\n", i); } + } + + if (ret != 0) + { + IPACMERR("Failed modifying filtering rule IOCTL for %pK\n", ruleTable); return false; } diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp index 0d4f54f..55cf71d 100644 --- a/ipacm/src/IPACM_Iface.cpp +++ b/ipacm/src/IPACM_Iface.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2020, 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 @@ -955,57 +955,6 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) memcpy(&(m_pFilteringTable->rules[4]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPV6_DEFAULT_FILTERTING_RULES); - memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); - - flt_rule_entry.at_rear = true; - flt_rule_entry.flt_rule_hdl = -1; - flt_rule_entry.status = -1; - - flt_rule_entry.rule.retain_hdr = 1; - flt_rule_entry.rule.to_uc = 0; - flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - flt_rule_entry.rule.eq_attrib_type = 1; - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap = 0; - - if(rx_prop->rx[0].attrib.attrib_mask & IPA_FLT_META_DATA) - { - if (IPACM_Iface::ipacmcfg->isIPAv3Supported()) - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<9); - else - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<14); - flt_rule_entry.rule.eq_attrib.metadata_meq32_present = 1; - flt_rule_entry.rule.eq_attrib.metadata_meq32.offset = 0; - flt_rule_entry.rule.eq_attrib.metadata_meq32.value = rx_prop->rx[0].attrib.meta_data; - flt_rule_entry.rule.eq_attrib.metadata_meq32.mask = rx_prop->rx[0].attrib.meta_data_mask; - } - - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); - flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; - flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; - - if (IPACM_Iface::ipacmcfg->isIPAv3Supported()) - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7); - else - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); - flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1; - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; - - /* add TCP FIN rule*/ - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT); - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT); - memcpy(&(m_pFilteringTable->rules[5]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - - /* add TCP SYN rule*/ - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT); - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT); - memcpy(&(m_pFilteringTable->rules[6]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - - /* add TCP RST rule*/ - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT); - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT); - memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - #endif #ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO /* use index hw-counter */ @@ -1060,7 +1009,7 @@ fail: return res; } -/* get ipa interface name */ +/* get ipa interface index from name */ int IPACM_Iface::ipa_get_if_index ( char * if_name, diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp index 2857f39..1392a1a 100644 --- a/ipacm/src/IPACM_IfaceManager.cpp +++ b/ipacm/src/IPACM_IfaceManager.cpp @@ -291,6 +291,9 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) 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); @@ -420,6 +423,9 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) 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); @@ -450,6 +456,12 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) 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 @@ -458,6 +470,9 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) 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); diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp index 0a532fd..c83a729 100644 --- a/ipacm/src/IPACM_Lan.cpp +++ b/ipacm/src/IPACM_Lan.cpp @@ -751,25 +751,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) if (ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n"); -#ifdef FEATURE_IPA_ANDROID - if (IPACM_Wan::isXlat() && (data->prefix.iptype == IPA_IP_v4)) - { - /* indicate v4-offload */ - IPACM_OffloadManager::num_offload_v4_tethered_iface++; - IPACMDBG_H("in xlat: update num_offload_v4_tethered_iface %d\n", IPACM_OffloadManager::num_offload_v4_tethered_iface); - - /* xlat not support for 2st tethered iface */ - if (IPACM_OffloadManager::num_offload_v4_tethered_iface > 1) - { - IPACMDBG_H("Not support 2st downstream iface %s for xlat, cur: %d\n", dev_name, - IPACM_OffloadManager::num_offload_v4_tethered_iface); - return; - } - } - IPACMDBG_H(" support downstream iface %s, cur %d\n", dev_name, - IPACM_OffloadManager::num_offload_v4_tethered_iface); -#endif if (data->prefix.iptype < IPA_IP_MAX && is_downstream_set[data->prefix.iptype] == false) { IPACMDBG_H("Add downstream for IP iptype %d\n", data->prefix.iptype); @@ -1128,6 +1110,36 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) } break; +#ifdef IPA_MTU_EVENT_MAX + case IPA_MTU_UPDATE: + { + IPACMDBG_H("Received IPA_MTU_UPDATE"); + ipacm_event_mtu_info *evt_data = (ipacm_event_mtu_info *)param; + ipa_mtu_info *data = &(evt_data->mtu_info); + + /* IPA_IP_MAX means both ipv4 and ipv6 */ + if ((data->ip_type == IPA_IP_v4 || data->ip_type == IPA_IP_MAX) && IPACM_Wan::isWanUP(ipa_if_num)) + { + handle_private_subnet_android(IPA_IP_v4); + } + + /* IPA_IP_MAX means both ipv4 and ipv6 */ + if ((data->ip_type == IPA_IP_v6 || data->ip_type == IPA_IP_MAX) && IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + /* check if the prefix + MTU rules are installed */ + if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1]) + { + modify_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + } + else + { + IPACMERR("Failed to update prefix MTU rules, no prefix rules set"); + } + } + } + break; +#endif + default: break; } @@ -1659,9 +1671,9 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) /* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */ if (IPACM_Wan::isWanUP_V6(ipa_if_num)) { - if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1] ) { - delete_ipv6_prefix_flt_rule(); - install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1]) + { + modify_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); } } @@ -1905,15 +1917,34 @@ int IPACM_Lan::handle_wan_up_ex(ipacm_ext_prop *ext_prop, ipa_ip_type iptype, ui ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id); modem_ul_v6_set = true; } else if (iptype ==IPA_IP_v4 && modem_ul_v4_set == false) { +#ifdef FEATURE_IPA_ANDROID + if (IPACM_Wan::isXlat()) + { + /* indicate v4-offload */ + IPACM_OffloadManager::num_offload_v4_tethered_iface++; + IPACMDBG_H("in xlat: update num_offload_v4_tethered_iface %d\n", IPACM_OffloadManager::num_offload_v4_tethered_iface); + + /* xlat not support for 2st tethered iface */ + if (IPACM_OffloadManager::num_offload_v4_tethered_iface > 1) + { + IPACMDBG_H("Not support 2st downstream iface %s for xlat, cur: %d\n", dev_name, + IPACM_OffloadManager::num_offload_v4_tethered_iface); + return IPACM_FAILURE; + } + } + + IPACMDBG_H(" support downstream iface %s, cur %d\n", dev_name, + IPACM_OffloadManager::num_offload_v4_tethered_iface); +#endif /* add MTU rules for ipv4 */ handle_private_subnet_android(IPA_IP_v4); /* Update ipv6 MTU here if WAN_v6 is up and filter rules were installed */ if (IPACM_Wan::isWanUP_V6(ipa_if_num)) { - if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1] ) { - delete_ipv6_prefix_flt_rule(); - install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1]) + { + modify_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); } } @@ -4205,9 +4236,14 @@ int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype) mtu[i] = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v4); if (mtu[i] > 0) + { mtu_rule_cnt++; + IPACMDBG_H("MTU[%d] is %d\n", i, mtu[i]); + } else - IPACMERR("MTU is zero\n"); + { + IPACMDBG_H("MTU is zero\n"); + } } IPACMDBG_H("total %d MTU rules are needed\n", mtu_rule_cnt); @@ -4237,16 +4273,16 @@ int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype) flt_rule.rule.retain_hdr = 1; flt_rule.rule.to_uc = 0; - flt_rule.rule.action = IPA_PASS_TO_ROUTING; - flt_rule.rule.eq_attrib_type = 0; - flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; IPACMDBG_H("Private filter rule use table: %s\n",IPACM_Iface::ipacmcfg->rt_tbl_default_v4.name); for (i = 0; i < (IPACM_Iface::ipacmcfg->ipa_num_private_subnet); i++) { /* add private subnet rule for ipv4 */ + /* these 3 properties below will be reset during construct_mtu_rule */ flt_rule.rule.action = IPA_PASS_TO_ROUTING; flt_rule.rule.eq_attrib_type = 0; + flt_rule.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_default_v4.hdl; + flt_rule.rule_hdl = private_fl_rule_hdl[i]; memcpy(&flt_rule.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule.rule.attrib)); flt_rule.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; @@ -4264,7 +4300,9 @@ int IPACM_Lan::handle_private_subnet_android(ipa_ip_type iptype) flt_rule.rule.attrib.u.v4.src_addr = IPACM_Iface::ipacmcfg->private_subnet_table[i].subnet_addr; flt_rule.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; if (construct_mtu_rule(&flt_rule.rule, IPA_IP_v4, mtu[i])) + { IPACMERR("Failed to modify MTU filtering rule.\n"); + } memcpy(&(pFilteringTable->rules[mtu_rule_idx + i]), &flt_rule, sizeof(struct ipa_flt_rule_mdfy)); IPACMDBG_H("Adding MTU rule for private subnet 0x%x.\n", flt_rule.rule.attrib.u.v4.src_addr); } @@ -4285,8 +4323,13 @@ fail: return res; } -int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) +int IPACM_Lan::modify_ipv6_prefix_flt_rule(uint32_t* prefix) { + int len, res = IPACM_SUCCESS; + struct ipa_flt_rule_mdfy flt_rule_entry; + struct ipa_ioc_mdfy_flt_rule* flt_rule; + int rule_cnt = 1; + if(prefix == NULL) { IPACMERR("IPv6 prefix is empty.\n"); @@ -4294,15 +4337,124 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) } IPACMDBG_H("Receive IPv6 prefix: 0x%08x%08x.\n", prefix[0], prefix[1]); + uint16_t mtu = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v6); + if (mtu > 0) + { + IPACMDBG_H("MTU is %d\n", mtu); + rule_cnt ++; + } + else + { + IPACMERR("MTU is 0"); + } + + + if(rx_prop == NULL) + { + IPACMERR("no rx props\n"); + return IPACM_FAILURE; + } + + len = sizeof(struct ipa_ioc_mdfy_flt_rule) + rule_cnt * sizeof(struct ipa_flt_rule_mdfy); + flt_rule = (struct ipa_ioc_mdfy_flt_rule*)malloc(len); + if(!flt_rule) + { + IPACMERR("Failed to allocate ipa_ioc_mdfy_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(flt_rule, 0, len); + + flt_rule->commit = 1; + flt_rule->ip = IPA_IP_v6; + flt_rule->num_rules = rule_cnt; + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_mdfy)); + flt_rule_entry.status = -1; + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.rule_hdl = ipv6_prefix_flt_rule_hdl[0]; + + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0x0; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0x0; + memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_mdfy)); + + + flt_rule_entry.rule_hdl = ipv6_prefix_flt_rule_hdl[1]; + memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(flt_rule_entry.rule.attrib)); // this will remove the IPA_FLT_DST_ADDR + flt_rule_entry.rule.attrib.u.v6.src_addr[3] = prefix[0]; + flt_rule_entry.rule.attrib.u.v6.src_addr[2] = prefix[1]; + flt_rule_entry.rule.attrib.u.v6.src_addr[1] = 0x0; + flt_rule_entry.rule.attrib.u.v6.src_addr[0] = 0x0; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = 0x0; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = 0x0; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + + /* Add an MTU rule with every new private prefix */ + if (mtu > 0) + { + if (construct_mtu_rule(&flt_rule_entry.rule, IPA_IP_v6, mtu)) + { + IPACMERR("Failed to add MTU filtering rule.\n") + } + else + { + memcpy(&(flt_rule->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_mdfy)); + } + } + + + if(false == m_filtering.ModifyFilteringRule(flt_rule)) + { + IPACMERR("Failed to modify prefix filtering rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + if(flt_rule != NULL) + { + free(flt_rule); + } + return res; +} + +int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) +{ int len; struct ipa_ioc_add_flt_rule* flt_rule; struct ipa_flt_rule_add flt_rule_entry; bool result; int rule_cnt = 1; + if(prefix == NULL) + { + IPACMERR("IPv6 prefix is empty.\n"); + return IPACM_FAILURE; + } + IPACMDBG_H("Receive IPv6 prefix: 0x%08x%08x.\n", prefix[0], prefix[1]); + uint16_t mtu = IPACM_Wan::queryMTU(ipa_if_num, IPA_IP_v6); if (mtu > 0) + { + IPACMDBG_H("MTU is %d\n", mtu); rule_cnt ++; + } + else + { + IPACMERR("MTU is 0"); + } if(rx_prop != NULL) { @@ -4368,18 +4520,7 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) } } -#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO - /* use index hw-counter */ - if(ipa_if_cate == WLAN_IF && IPACM_Iface::ipacmcfg->hw_fnr_stats_support) - { - IPACMDBG_H("hw-index-enable %d, counter %d\n", IPACM_Iface::ipacmcfg->hw_fnr_stats_support, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); - result = m_filtering.AddFilteringRule_hw_index(flt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); - } else { - result = m_filtering.AddFilteringRule(flt_rule); - } -#else result = m_filtering.AddFilteringRule(flt_rule); -#endif if (result == false) { @@ -6467,6 +6608,7 @@ int IPACM_Lan::construct_mtu_rule(struct ipa_flt_rule *rule, ipa_ip_type iptype, rule->eq_attrib_type = 1; rule->eq_attrib.rule_eq_bitmap = 0; rule->action = IPA_PASS_TO_EXCEPTION; + rule->rt_tbl_hdl = -1; /* generate eq */ memset(&flt_eq, 0, sizeof(flt_eq)); @@ -6490,7 +6632,11 @@ int IPACM_Lan::construct_mtu_rule(struct ipa_flt_rule *rule, ipa_ip_type iptype, &flt_eq.eq_attrib, sizeof(rule->eq_attrib)); //add IHL offsets - rule->eq_attrib.rule_eq_bitmap |= (1<<10); +#ifdef FEATURE_IPA_V3 + rule->eq_attrib.rule_eq_bitmap |= (1<<10); +#else + rule->eq_attrib.rule_eq_bitmap |= (1<<4); +#endif rule->eq_attrib.num_ihl_offset_range_16 = 1; if (iptype == IPA_IP_v4) rule->eq_attrib.ihl_offset_range_16[0].offset = 0x82; diff --git a/ipacm/src/IPACM_LanToLan.cpp b/ipacm/src/IPACM_LanToLan.cpp index ea016ef..0075418 100644 --- a/ipacm/src/IPACM_LanToLan.cpp +++ b/ipacm/src/IPACM_LanToLan.cpp @@ -1308,8 +1308,12 @@ void IPACM_LanToLan_Iface::handle_down_event() it_own_peer_info++) { /* decrement reference count of peer l2 header type on both interfaces*/ - decrement_ref_cnt_peer_l2_hdr_type(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type); - it_own_peer_info->peer->decrement_ref_cnt_peer_l2_hdr_type(m_p_iface->tx_prop->tx[0].hdr_l2_type); + if (it_own_peer_info->peer && + it_own_peer_info->peer->get_iface_pointer() && + it_own_peer_info->peer->get_iface_pointer()->tx_prop) + decrement_ref_cnt_peer_l2_hdr_type(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type); + if (it_own_peer_info->peer && m_p_iface && m_p_iface->tx_prop) + it_own_peer_info->peer->decrement_ref_cnt_peer_l2_hdr_type(m_p_iface->tx_prop->tx[0].hdr_l2_type); /* first clear all flt rule on target interface */ IPACMDBG_H("Clear all flt rule on target interface.\n"); @@ -1330,7 +1334,8 @@ void IPACM_LanToLan_Iface::handle_down_event() other_iface->clear_all_rt_rule_for_one_peer_iface(&(*it_other_iface_peer_info)); /* remove the peer info from the list */ other_iface->m_peer_iface_info.erase(it_other_iface_peer_info); - other_iface->del_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type); + if (m_p_iface && m_p_iface->tx_prop) + other_iface->del_hdr_proc_ctx(m_p_iface->tx_prop->tx[0].hdr_l2_type); break; } } @@ -1338,6 +1343,9 @@ void IPACM_LanToLan_Iface::handle_down_event() /* then clear rt rule and hdr proc ctx and release rt table on target interface */ IPACMDBG_H("Clear rt rules and hdr proc ctx and release rt table on target interface.\n"); clear_all_rt_rule_for_one_peer_iface(&(*it_own_peer_info)); + if (it_own_peer_info->peer && + it_own_peer_info->peer->get_iface_pointer() && + it_own_peer_info->peer->get_iface_pointer()->tx_prop) del_hdr_proc_ctx(it_own_peer_info->peer->get_iface_pointer()->tx_prop->tx[0].hdr_l2_type); } m_peer_iface_info.clear(); diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp index 696f518..6bd117e 100644 --- a/ipacm/src/IPACM_Main.cpp +++ b/ipacm/src/IPACM_Main.cpp @@ -121,7 +121,7 @@ int ipa_reset_hw_index_counter(); #ifdef FEATURE_IPACM_HAL IPACM_OffloadManager* OffloadMng; - HAL *hal; + ::android::sp<HAL> hal; #endif /* start netlink socket monitor*/ @@ -270,6 +270,10 @@ void* ipa_driver_msg_notifier(void *param) #endif ipacm_cmd_q_data new_neigh_evt; ipacm_event_data_all* new_neigh_data; +#ifdef IPA_MTU_EVENT_MAX + ipacm_event_mtu_info *mtu_event = NULL; + ipa_mtu_info *mtu_info; +#endif param = NULL; fd = open(IPA_DRIVER, O_RDWR); @@ -760,10 +764,19 @@ void* ipa_driver_msg_notifier(void *param) IPACMERR("calling OffloadMng->elrInstance->onOffloadStopped \n"); OffloadMng->elrInstance->onOffloadStopped(IpaEventRelay::ERROR); } - /* WA to clean up wlan instances during SSR */ - evt_data.event = IPA_SSR_NOTICE; - evt_data.evt_data = NULL; - break; + /* Starting from Hastings, WLAN is not restarted as part of Modem SSR. + * No need to reset NAT Iface. + */ +#ifdef IPA_HW_v4_9 + if (IPACM_Iface::ipacmcfg->GetIPAVer() != IPA_HW_v4_9) +#endif + { + /* WA to clean up wlan instances during SSR */ + evt_data.event = IPA_SSR_NOTICE; + evt_data.evt_data = NULL; + break; + } + continue; case IPA_SSR_AFTER_POWERUP: IPACMDBG_H("Received IPA_SSR_AFTER_POWERUP\n"); OffloadMng = IPACM_OffloadManager::GetInstance(); @@ -865,6 +878,32 @@ void* ipa_driver_msg_notifier(void *param) break; #endif +#ifdef IPA_MTU_EVENT_MAX + case IPA_SET_MTU: + mtu_event = (ipacm_event_mtu_info *)malloc(sizeof(*mtu_event)); + if(mtu_event == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return NULL; + } + mtu_info = &(mtu_event->mtu_info); + memcpy(mtu_info, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_mtu_info)); + IPACMDBG_H("Received IPA_SET_MTU if_name %s ip_type %d mtu_v4 %d mtu_v6 %d\n", + mtu_info->if_name, mtu_info->ip_type, mtu_info->mtu_v4, mtu_info->mtu_v6); + if (mtu_info->ip_type > IPA_IP_MAX) + { + IPACMERR("ip_type (%d) beyond the Max range (%d), abort\n", + mtu_info->ip_type, IPA_IP_MAX); + return NULL; + } + + ipa_get_if_index(mtu_info->if_name, &(mtu_event->if_index)); + + evt_data.event = IPA_MTU_SET; + evt_data.evt_data = mtu_event; + break; +#endif + default: IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type); continue; diff --git a/ipacm/src/IPACM_OffloadManager.cpp b/ipacm/src/IPACM_OffloadManager.cpp index 7919413..708725b 100644 --- a/ipacm/src/IPACM_OffloadManager.cpp +++ b/ipacm/src/IPACM_OffloadManager.cpp @@ -120,8 +120,9 @@ RET IPACM_OffloadManager::unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* ) RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) { + struct timeval tv; IPACM_ConntrackClient *cc; - int on = 1, rel; + int on = 1, rel = 0; struct sockaddr_nl local; unsigned int addr_len; @@ -155,13 +156,39 @@ RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) ); } } else if (groups == cc->subscrips_udp) { + /* Set receive timeout to 1s on the FD which is used to read conntrack dump. */ + memset(&tv,0, sizeof(struct timeval)); + tv.tv_sec = 1; /* 1s timeout */ + rel = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); + if (rel == -1) + { + IPACMERR("setsockopt returned error code %d ( %s )\n", errno, strerror(errno)); + } + + /* In Android we get conntrack handles once after tethering is enabled but we + loose connections info for embedded traffic if running before. So no NAT + entries are added for embedded traffic due to which we see NAT exception and + data takes S/W path which results in less throughput. Hence for embedded + traffic info, framework sends conntrack dump before providing handles. Here + reading ct entries before creating filter on Fd in order to have NAT entries + for both TCP/UDP embedded traffic. + */ + CtList->readConntrack(fd); + /* Reset receive timeout on the FD which is used to read conntrack dump. */ + memset(&tv,0, sizeof(struct timeval)); + rel = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); + if (rel == -1) + { + IPACMERR("setsockopt returned error code %d ( %s )\n", errno, strerror(errno)); + } + cc->fd_udp = dup(fd); IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups); /* set netlink buf */ - rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) ); + rel = setsockopt(cc->fd_udp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) ); if (rel == -1) { - IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) ); + IPACMERR("setsockopt returned error code %d ( %s )\n", errno, strerror(errno)); } } else { IPACMERR("Received unexpected fd with groups %d.\n", groups); diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp index 847e08d..f17eb03 100644 --- a/ipacm/src/IPACM_Wan.cpp +++ b/ipacm/src/IPACM_Wan.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. +Copyright (c) 2013-2020 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 @@ -92,7 +92,8 @@ int IPACM_Wan::ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES]; int IPACM_Wan::ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES]; #endif -uint16_t IPACM_Wan::mtu_default_wan = DEFAULT_MTU_SIZE; +uint16_t IPACM_Wan::mtu_default_wan_v4 = DEFAULT_MTU_SIZE; +uint16_t IPACM_Wan::mtu_default_wan_v6 = DEFAULT_MTU_SIZE; IPACM_Wan::IPACM_Wan(int iface_index, ipacm_wan_iface_type is_sta_mode, @@ -132,7 +133,11 @@ IPACM_Wan::IPACM_Wan(int iface_index, ext_prop = NULL; is_ipv6_frag_firewall_flt_rule_installed = false; ipv6_frag_firewall_flt_rule_hdl = 0; - mtu_size = DEFAULT_MTU_SIZE; + + mtu_v4 = DEFAULT_MTU_SIZE; + mtu_v4_set = false; + mtu_v6 = DEFAULT_MTU_SIZE; + mtu_v6_set = false; num_wan_client = 0; header_name_count = 0; @@ -146,6 +151,53 @@ IPACM_Wan::IPACM_Wan(int iface_index, wan_client_len = 0; m_is_sta_mode = is_sta_mode; +#ifdef IPA_MTU_EVENT_MAX + /* Query WAN MTU to handle IPACM restart scenarios. */ + if(is_sta_mode == Q6_WAN) + { + int fd_wwan_ioctl; + ipa_mtu_info *mtu_info = (ipa_mtu_info *)malloc(sizeof(ipa_mtu_info)); + if (mtu_info) + { + memset(mtu_info, 0, sizeof(ipa_mtu_info)); + memcpy(mtu_info->if_name, dev_name, IPA_IFACE_NAME_LEN); + fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + } + else + { + IPACMDBG_H("send WAN_IOC_GET_WAN_MTU for %s\n", mtu_info->if_name); + if(ioctl(fd_wwan_ioctl, WAN_IOC_GET_WAN_MTU, mtu_info)) + { + IPACMERR("Failed to send WAN_IOC_GET_WAN_MTU\n "); + } + else + { + /* Updated MTU values.*/ + if (mtu_info->mtu_v4) + { + mtu_v4 = mtu_info->mtu_v4; + mtu_v4_set = true; + IPACMDBG_H("Updated v4 mtu=[%d] for (%s)\n", + mtu_v4, mtu_info->if_name); + } + if (mtu_info->mtu_v6) + { + mtu_v6 = mtu_info->mtu_v6; + mtu_v6_set = true; + IPACMDBG_H("Updated v6 mtu=[%d] for (%s)\n", + mtu_v6, mtu_info->if_name); + } + } + close(fd_wwan_ioctl); + } + free(mtu_info); + } + } +#endif + if(iface_query != NULL) { IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); @@ -810,7 +862,7 @@ int IPACM_Wan::handle_addr_evt_mhi_q6(ipacm_event_data_addr *data) IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v6); IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v6); } - /* skylar setup v6-wan-tbl */ + /* setup v6-wan-tbl */ rt_rule = (struct ipa_ioc_add_rt_rule *) calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + NUM_RULES * sizeof(struct ipa_rt_rule_add)); @@ -1112,6 +1164,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } } break; + case IPA_LINK_DOWN_EVENT: { ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; @@ -1575,6 +1628,8 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { ipacm_event_data_all *data = (ipacm_event_data_all *)param; ipa_interface_index = iface_ipa_index_query(data->if_index); + int index = 0; + bool renew = false; if (ipa_interface_index == ipa_if_num) { @@ -1606,6 +1661,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } IPACMDBG_H("wan-iface got client \n"); + /* first construc WAN-client full header */ if(memcmp(data->mac_addr, invalid_mac, @@ -1617,7 +1673,20 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) return; } - handle_wan_hdr_init(data->mac_addr); + /* check if same as GW_ip need replacing */ + if( handle_gw_mac_renew(data, index) == IPACM_SUCCESS) + { + renew = true; + IPACMDBG_H("Renew is happening with client-index (%d)\n", index); + /* clinet renew procedure */ + handle_wan_hdr_init(data->mac_addr, true, index); + } + else + { + IPACMDBG_H("Renew is no need!\n"); + handle_wan_hdr_init(data->mac_addr); + } + IPACMDBG_H("construct wan-client header and route rules \n"); /* Associate with IP and construct RT-rule */ if (handle_wan_client_ipaddr(data) == IPACM_FAILURE) @@ -1626,7 +1695,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } handle_wan_client_route_rule(data->mac_addr, data->iptype); /* Check & construct STA header */ - handle_sta_header_add_evt(); + handle_sta_header_add_evt(renew); return; } } @@ -1721,54 +1790,117 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } break; - case IPA_WLAN_SWITCH_TO_SCC: - if(IPACM_Wan::backhaul_mode == WLAN_WAN) + case IPA_WLAN_SWITCH_TO_SCC: + if(IPACM_Wan::backhaul_mode == WLAN_WAN) + { + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); + if(ip_type == IPA_IP_MAX) { - IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); - if(ip_type == IPA_IP_MAX) - { - handle_wlan_SCC_MCC_switch(true, IPA_IP_v4); - handle_wlan_SCC_MCC_switch(true, IPA_IP_v6); - handle_wan_client_SCC_MCC_switch(true, IPA_IP_v4); - handle_wan_client_SCC_MCC_switch(true, IPA_IP_v6); - } - else - { - handle_wlan_SCC_MCC_switch(true, ip_type); - handle_wan_client_SCC_MCC_switch(true, ip_type); - } + handle_wlan_SCC_MCC_switch(true, IPA_IP_v4); + handle_wlan_SCC_MCC_switch(true, IPA_IP_v6); + handle_wan_client_SCC_MCC_switch(true, IPA_IP_v4); + handle_wan_client_SCC_MCC_switch(true, IPA_IP_v6); } - break; + else + { + handle_wlan_SCC_MCC_switch(true, ip_type); + handle_wan_client_SCC_MCC_switch(true, ip_type); + } + } + break; + + case IPA_WLAN_SWITCH_TO_MCC: + if(IPACM_Wan::backhaul_mode == WLAN_WAN) + { + IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); + if(ip_type == IPA_IP_MAX) + { + handle_wlan_SCC_MCC_switch(false, IPA_IP_v4); + handle_wlan_SCC_MCC_switch(false, IPA_IP_v6); + handle_wan_client_SCC_MCC_switch(false, IPA_IP_v4); + handle_wan_client_SCC_MCC_switch(false, IPA_IP_v6); + } + else + { + handle_wlan_SCC_MCC_switch(false, ip_type); + handle_wan_client_SCC_MCC_switch(false, ip_type); + } + } + break; +#ifdef FEATURE_IPACM_HAL + /* WA for WLAN to clean up NAT instance during SSR */ + case IPA_SSR_NOTICE: + case IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE: + { + IPACMDBG_H("Received IPA_SSR_NOTICE event.\n"); + if(m_is_sta_mode == WLAN_WAN) + { + IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + } + } + break; +#endif +#ifdef IPA_MTU_EVENT_MAX + case IPA_MTU_SET: + { + ipacm_event_mtu_info *data = (ipacm_event_mtu_info *)param; + ipa_mtu_info *mtu_info = &(data->mtu_info); + ipa_interface_index = iface_ipa_index_query(data->if_index); - case IPA_WLAN_SWITCH_TO_MCC: - if(IPACM_Wan::backhaul_mode == WLAN_WAN) + if (ipa_interface_index == ipa_if_num) + { + IPACMDBG_H("Received IPA_MTU_SET (Android) for interface (%d)\n", + ipa_interface_index); + if (mtu_info->ip_type == IPA_IP_v4 || mtu_info->ip_type == IPA_IP_MAX) { - IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); - if(ip_type == IPA_IP_MAX) + /* Update v4_mtu. */ + mtu_v4 = mtu_info->mtu_v4; + mtu_v4_set = true; + + if (active_v4) { - handle_wlan_SCC_MCC_switch(false, IPA_IP_v4); - handle_wlan_SCC_MCC_switch(false, IPA_IP_v6); - handle_wan_client_SCC_MCC_switch(false, IPA_IP_v4); - handle_wan_client_SCC_MCC_switch(false, IPA_IP_v6); + /* upstream interface. update default MTU. */ + mtu_default_wan_v4 = mtu_v4; } - else + IPACMDBG_H("Updated v4 mtu=[%d] for (%s), upstream_mtu=[%d]\n", + mtu_v4, mtu_info->if_name, mtu_default_wan_v4); + } + if (mtu_info->ip_type == IPA_IP_v6 || mtu_info->ip_type == IPA_IP_MAX) + { + /* Update v4_mtu. */ + mtu_v6 = mtu_info->mtu_v6; + mtu_v6_set = true; + if (active_v6) { - handle_wlan_SCC_MCC_switch(false, ip_type); - handle_wan_client_SCC_MCC_switch(false, ip_type); + /* upstream interface. update default MTU. */ + mtu_default_wan_v6 = mtu_v6; } + IPACMDBG_H("Updated v6 mtu=[%d] for (%s), upstream_mtu=[%d]\n", + mtu_v6, mtu_info->if_name, mtu_default_wan_v6); } - break; -#ifdef FEATURE_IPACM_HAL - /* WA for WLAN to clean up NAT instance during SSR */ - case IPA_SSR_NOTICE: - case IPA_WLAN_FWR_SSR_BEFORE_SHUTDOWN_NOTICE: - IPACMDBG_H("Received IPA_SSR_NOTICE event.\n"); - if(m_is_sta_mode == WLAN_WAN) + + if (active_v4 || active_v6) { - IPACM_Iface::ipacmcfg->DelNatIfaces(dev_name); // delete NAT-iface + ipacm_event_mtu_info *mtu_event; + ipacm_cmd_q_data evt_data; + mtu_event = (ipacm_event_mtu_info *)malloc(sizeof(*mtu_event)); + if(mtu_event == NULL) + { + IPACMERR("Failed to allocate memory.\n"); + return; + } + memcpy(&mtu_event->mtu_info, mtu_info, sizeof(ipa_mtu_info)); + evt_data.event = IPA_MTU_UPDATE; + evt_data.evt_data = mtu_event; + /* finish command queue */ + IPACMDBG_H("Posting IPA_MTU_UPDATE event\n"); + IPACM_EvtDispatcher::PostEvt(&evt_data); } - break; + } + } + break; #endif + default: break; } @@ -1777,9 +1909,8 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } /* wan default route/filter rule configuration */ -int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) +int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype, bool add_only) { - /* add default WAN route */ struct ipa_ioc_add_rt_rule *rt_rule = NULL; struct ipa_rt_rule_add *rt_rule_entry; @@ -1817,8 +1948,14 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } IPACMDBG_H("backhaul_is_wan_bridge ?: %d \n", IPACM_Wan::backhaul_is_wan_bridge); - /* query MTU size of the interface */ - query_mtu_size(); + /* query MTU size of the interface if MTU is not set via ioctl. */ + if (!mtu_v4_set && !mtu_v6_set) + { + if(query_mtu_size()) + { + IPACMERR("Failed to query mtu"); + } + } if (m_is_sta_mode ==Q6_WAN) { @@ -2104,10 +2241,16 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) wan_route_rule_v6_hdl_a5[0], 0, iptype); } - /* set mtu_default_wan to current default wan instance */ - mtu_default_wan = mtu_size; - - IPACMDBG_H("replace the mtu_default_wan to %d\n", mtu_default_wan); + /* support delete only, not post wan_down event */ + if (add_only) + { + IPACMDBG_H(" Only add default WAN routing rules (%d)\n", add_only); + if(rt_rule != NULL) + { + free(rt_rule); + } + return IPACM_SUCCESS; + } ipacm_event_iface_up *wanup_data; wanup_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); @@ -2122,6 +2265,10 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) /* handling filter rule construction */ if (iptype == IPA_IP_v4) { + /* set mtu_default_wan to current default wan instance */ + mtu_default_wan_v4 = mtu_v4; + IPACMDBG_H("replace the mtu_wan to %d\n", mtu_default_wan_v4); + IPACM_Wan::wan_up = true; active_v4 = true; memcpy(IPACM_Wan::wan_up_dev_name, @@ -2181,6 +2328,10 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } else { + /* set mtu_default_wan to current default wan instance */ + mtu_default_wan_v6 = mtu_v6; + IPACMDBG_H("replace the mtu_wan to %d\n", mtu_default_wan_v6); + memcpy(backhaul_ipv6_prefix, ipv6_prefix, sizeof(backhaul_ipv6_prefix)); IPACMDBG_H("Setup backhaul ipv6 prefix to be 0x%08x%08x.\n", backhaul_ipv6_prefix[0], backhaul_ipv6_prefix[1]); @@ -2236,11 +2387,28 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE up to IPA_PM\n"); wan_state.up = true; +#ifdef WAN_IOCTL_NOTIFY_WAN_INTF_NAME + strlcpy(wan_state.upstreamIface, dev_name, IFNAMSIZ); +#endif if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state)) { IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up); } close(fd_wwan_ioctl); + + /* Store the Offload state. */ + FILE *fp = NULL; + fp = fopen(IPA_OFFLOAD_TETHER_STATE_FILE_NAME, "w"); + if (fp == NULL) + { + IPACMERR("Failed to write offload state to %s, error is %d - %s\n", + IPA_OFFLOAD_TETHER_STATE_FILE_NAME, errno, strerror(errno)); + } + else + { + fprintf(fp, "UPSTREAM=%s,STATE=UP", dev_name); + fclose(fp); + } } ipa_pm_q6_check++; IPACMDBG_H("update ipa_pm_q6_check to %d\n", ipa_pm_q6_check); @@ -2368,7 +2536,7 @@ int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tethe #endif /* construct complete ethernet header */ -int IPACM_Wan::handle_sta_header_add_evt() +int IPACM_Wan::handle_sta_header_add_evt(bool renew) { int res = IPACM_SUCCESS, index = IPACM_INVALID_INDEX; if((header_set_v4 == true) || (header_set_v6 == true)) @@ -2425,7 +2593,13 @@ int IPACM_Wan::handle_sta_header_add_evt() } } - /* checking if the ipv4 same as default route */ + /* see if v4 default routes are setup before constructing full header */ + if(header_partial_default_wan_v4 == true) + { + handle_route_add_evt(IPA_IP_v4, renew); + } + + /* checking if the ipv6 same as default route */ if(wan_v6_addr_gw_set) { index = get_wan_client_index_ipv6(wan_v6_addr_gw); @@ -2473,15 +2647,11 @@ int IPACM_Wan::handle_sta_header_add_evt() } } - /* see if default routes are setup before constructing full header */ - if(header_partial_default_wan_v4 == true) - { - handle_route_add_evt(IPA_IP_v4); - } + /* see if v6 default routes are setup before constructing full header */ if(header_partial_default_wan_v6 == true) { - handle_route_add_evt(IPA_IP_v6); + handle_route_add_evt(IPA_IP_v6, renew); } return res; } @@ -4257,9 +4427,6 @@ int IPACM_Wan::config_wan_firewall_rule(ipa_ip_type iptype) } else if(iptype == IPA_IP_v6) { -#ifdef FEATURE_IPA_ANDROID - add_tcpv6_filtering_rule(flt_rule_v6, IPACM_Wan::num_v6_flt_rule); -#endif IPACM_Wan::num_v6_flt_rule = IPA_V2_NUM_DEFAULT_WAN_FILTER_RULE_IPV6; if(IPACM_FAILURE == add_icmp_alg_rules(flt_rule_v6, IPACM_Wan::num_v6_flt_rule, IPA_IP_v6)) { @@ -4544,103 +4711,6 @@ fail: return res; } -int IPACM_Wan::add_tcpv6_filtering_rule(struct ipa_flt_rule_add *rules, int rule_offset) -{ - struct ipa_ioc_get_rt_tbl_indx rt_tbl_idx; - struct ipa_flt_rule_add flt_rule_entry; - struct ipa_ioc_generate_flt_eq flt_eq; - int res = IPACM_SUCCESS; - - if(rules == NULL) - { - IPACMERR("No filtering table available.\n"); - return IPACM_FAILURE; - } - if(rx_prop == NULL) - { - IPACMERR("No tx property.\n"); - return IPACM_FAILURE; - } - - memset(&rt_tbl_idx, 0, sizeof(rt_tbl_idx)); - strlcpy(rt_tbl_idx.name, IPACM_Iface::ipacmcfg->rt_tbl_wan_dl.name, IPA_RESOURCE_NAME_MAX); - rt_tbl_idx.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; - rt_tbl_idx.ip = IPA_IP_v6; - if(0 != ioctl(m_fd_ipa, IPA_IOC_QUERY_RT_TBL_INDEX, &rt_tbl_idx)) - { - IPACMERR("Failed to get routing table index from name\n"); - res = IPACM_FAILURE; - goto fail; - } - - IPACMDBG_H("Routing table %s has index %d\n", rt_tbl_idx.name, rt_tbl_idx.idx); - memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); - - flt_rule_entry.at_rear = true; - flt_rule_entry.flt_rule_hdl = -1; - flt_rule_entry.status = -1; - - flt_rule_entry.rule.retain_hdr = 1; - flt_rule_entry.rule.to_uc = 0; - flt_rule_entry.rule.eq_attrib_type = 1; - flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - flt_rule_entry.rule.rt_tbl_idx = rt_tbl_idx.idx; - -#ifdef FEATURE_IPA_ANDROID - IPACMDBG_H("Add TCP ctrl rules: total num %d\n", IPA_V2_NUM_TCP_WAN_FILTER_RULE_IPV6); -#endif - memcpy(&flt_rule_entry.rule.attrib, - &rx_prop->rx[0].attrib, - sizeof(flt_rule_entry.rule.attrib)); - memset(&flt_eq, 0, sizeof(flt_eq)); - memcpy(&flt_eq.attrib, &flt_rule_entry.rule.attrib, sizeof(flt_eq.attrib)); - flt_eq.ip = IPA_IP_v6; - if(0 != ioctl(m_fd_ipa, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) - { - IPACMERR("Failed to get eq_attrib\n"); - res = IPACM_FAILURE; - goto fail; - } - - memcpy(&flt_rule_entry.rule.eq_attrib, - &flt_eq.eq_attrib, - sizeof(flt_rule_entry.rule.eq_attrib)); - - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<1); - flt_rule_entry.rule.eq_attrib.protocol_eq_present = 1; - flt_rule_entry.rule.eq_attrib.protocol_eq = IPACM_FIREWALL_IPPROTO_TCP; - - if (IPACM_Iface::ipacmcfg->isIPAv3Supported()) - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7); - else - flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); - flt_rule_entry.rule.eq_attrib.num_ihl_offset_meq_32 = 1; - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].offset = 12; - - /* add TCP FIN rule*/ - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_FIN_SHIFT); - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_FIN_SHIFT); - memcpy(&(rules[rule_offset]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - - /* add TCP SYN rule*/ - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_SYN_SHIFT); - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_SYN_SHIFT); - memcpy(&(rules[rule_offset + 1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - - /* add TCP RST rule*/ - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].value = (((uint32_t)1)<<TCP_RST_SHIFT); - flt_rule_entry.rule.eq_attrib.ihl_offset_meq_32[0].mask = (((uint32_t)1)<<TCP_RST_SHIFT); - memcpy(&(rules[rule_offset + 2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - -#ifdef FEATURE_IPA_ANDROID - IPACM_Wan::num_v6_flt_rule += IPA_V2_NUM_TCP_WAN_FILTER_RULE_IPV6; - IPACMDBG_H("Constructed %d ICMP filtering rules for ip type %d\n", IPA_V2_NUM_TCP_WAN_FILTER_RULE_IPV6, IPA_IP_v6); -#endif - -fail: - return res; -} - int IPACM_Wan::del_wan_firewall_rule(ipa_ip_type iptype) { if(iptype == IPA_IP_v4) @@ -4769,7 +4839,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) } /* for STA mode: wan default route/filter rule delete */ -int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) +int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype, bool delete_only) { uint32_t tx_index; ipacm_cmd_q_data evt_data; @@ -4778,6 +4848,7 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) int fd_wwan_ioctl; memset(&wan_state, 0, sizeof(wan_state)); #endif + int ret = IPACM_SUCCESS; IPACMDBG_H("got handle_route_del_evt for STA-mode with ip-family:%d \n", iptype); @@ -4793,39 +4864,42 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) if (((iptype == IPA_IP_v4) && (active_v4 == true)) || ((iptype == IPA_IP_v6) && (active_v6 == true))) { - if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0) - { - /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ - IPACMDBG_H("dev %s delete producer dependency\n", dev_name); - IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); - IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); - } - else + if (!delete_only) { - /* change wan_state for Q6_MHI */ -#ifdef WAN_IOC_NOTIFY_WAN_STATE - IPACMDBG_H("ipa_pm_q6_check to %d\n", ipa_pm_q6_check); - if(ipa_pm_q6_check == 1 && m_is_sta_mode == Q6_MHI_WAN) + if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0) { - fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); - if(fd_wwan_ioctl < 0) - { - IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); - return false; - } - IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE down to IPA_PM\n"); - if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state)) - { - IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up); - } - close(fd_wwan_ioctl); + /* Delete corresponding ipa_rm_resource_name of TX-endpoint after delete IPV4/V6 RT-rule */ + IPACMDBG_H("dev %s delete producer dependency\n", dev_name); + IPACMDBG_H("depend Got pipe %d rm index : %d \n", tx_prop->tx[0].dst_pipe, IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); + IPACM_Iface::ipacmcfg->DelRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe]); } - if (ipa_pm_q6_check > 0) - ipa_pm_q6_check--; else - IPACMERR(" ipa_pm_q6_check becomes negative !!!\n"); + { + /* change wan_state for Q6_MHI */ +#ifdef WAN_IOC_NOTIFY_WAN_STATE + IPACMDBG_H("ipa_pm_q6_check to %d\n", ipa_pm_q6_check); + if(ipa_pm_q6_check == 1 && m_is_sta_mode == Q6_MHI_WAN) + { + fd_wwan_ioctl = open(WWAN_QMI_IOCTL_DEVICE_NAME, O_RDWR); + if(fd_wwan_ioctl < 0) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return false; + } + IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE down to IPA_PM\n"); + if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state)) + { + IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up); + } + close(fd_wwan_ioctl); + } + if (ipa_pm_q6_check > 0) + ipa_pm_q6_check--; + else + IPACMERR(" ipa_pm_q6_check becomes negative !!!\n"); #endif - } + } + } // end of delete_only for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { @@ -4868,6 +4942,14 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) return IPACM_FAILURE; } } + + /* support delete only, not post wan_down event */ + if(delete_only) + { + IPACMDBG_H(" Only delete default WAN routing rules (%d)\n", delete_only); + return IPACM_SUCCESS; + } + ipacm_event_iface_up *wandown_data; wandown_data = (ipacm_event_iface_up *)malloc(sizeof(ipacm_event_iface_up)); if (wandown_data == NULL) @@ -4907,24 +4989,19 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) if(delete_offload_frag_rule()) { IPACMERR("Failed to delete DL frag rule \n"); - return IPACM_FAILURE; - } - /* Delete MHI icmpv6 exception rule */ - if(delete_icmpv6_exception_rule()) - { - IPACMERR("Failed to delete icmpv6 rule \n"); - return IPACM_FAILURE; + ret = IPACM_FAILURE; } + /* Delete tcp_fin_rst rule */ if(delete_tcp_fin_rst_exception_rule()) { IPACMERR("Failed to delete tcp_fin_rst rule \n"); - return IPACM_FAILURE; + ret = IPACM_FAILURE; } + return ret; } else { - wandown_data->backhaul_type = m_is_sta_mode; memcpy(wandown_data->ipv6_prefix, ipv6_prefix, sizeof(wandown_data->ipv6_prefix)); evt_data.event = IPA_HANDLE_WAN_DOWN_V6; @@ -4943,6 +5020,13 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) { memset(IPACM_Wan::wan_up_dev_name, 0, sizeof(IPACM_Wan::wan_up_dev_name)); } + /* Delete MHI icmpv6 exception rule */ + if(delete_icmpv6_exception_rule()) + { + IPACMERR("Failed to delete icmpv6 rule \n"); + return IPACM_FAILURE; + } + } } else @@ -4995,11 +5079,28 @@ int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype) return false; } IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE down to IPA_PM\n"); +#ifdef WAN_IOCTL_NOTIFY_WAN_INTF_NAME + strlcpy(wan_state.upstreamIface, dev_name, IFNAMSIZ); +#endif if(ioctl(fd_wwan_ioctl, WAN_IOC_NOTIFY_WAN_STATE, &wan_state)) { IPACMERR("Failed to send WAN_IOC_NOTIFY_WAN_STATE as up %d\n ", wan_state.up); } close(fd_wwan_ioctl); + + /* Store the Offload state. */ + FILE *fp = NULL; + fp = fopen(IPA_OFFLOAD_TETHER_STATE_FILE_NAME, "w"); + if (fp == NULL) + { + IPACMERR("Failed to write offload state to %s, error is %d - %s\n", + IPA_OFFLOAD_TETHER_STATE_FILE_NAME, errno, strerror(errno)); + } + else + { + fprintf(fp, "UPSTREAM=%s,STATE=DOWN", dev_name); + fclose(fp); + } } if (ipa_pm_q6_check > 0) ipa_pm_q6_check--; @@ -5243,17 +5344,6 @@ int IPACM_Wan::handle_down_evt() handle_route_del_evt(IPA_IP_v4); IPACMDBG_H("Delete default v4 routing rules\n"); - if(m_is_sta_mode == Q6_MHI_WAN) - { - /* Delete default v4 RT rule */ - IPACMDBG_H("Delete default v4 routing rules\n"); - if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) - { - IPACMERR("Routing v6-lan-RT rule deletion failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - } #ifdef FEATURE_IPA_ANDROID /* posting wan_down_tether for lan clients */ @@ -5285,18 +5375,6 @@ int IPACM_Wan::handle_down_evt() handle_route_del_evt(IPA_IP_v6); IPACMDBG_H("Delete default v6 routing rules\n"); - if(m_is_sta_mode == Q6_MHI_WAN) - { - /* Delete default v6 RT rule */ - IPACMDBG_H("Delete default v6 routing rules\n"); - if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[1], IPA_IP_v6) == false) - { - IPACMERR("Routing v6-wan-RT rule deletion failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - } - #ifdef FEATURE_IPA_ANDROID /* posting wan_down_tether for lan clients */ #ifdef FEATURE_IPACM_HAL @@ -5318,37 +5396,51 @@ int IPACM_Wan::handle_down_evt() #endif } - if(m_is_sta_mode != Q6_MHI_WAN) + /* Delete default v4 RT rule */ + if (ip_type != IPA_IP_v6 && wan_v4_addr_set) { - /* Delete default v4 RT rule */ - if (ip_type != IPA_IP_v6) + /* no need delete v4 RSC routing rules */ + IPACMDBG_H("Delete default v4 routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } + + /* delete default v6 RT rule */ + if (ip_type != IPA_IP_v4) + { + IPACMDBG_H("Delete default v6 routing rules\n"); + /* May have multiple ipv6 iface-routing rules*/ + for (i = 0; i < 2*num_dft_rt_v6; i++) { - /* no need delete v4 RSC routing rules */ - IPACMDBG_H("Delete default v4 routing rules\n"); - if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) { IPACMERR("Routing rule deletion failed!\n"); res = IPACM_FAILURE; goto fail; } } + IPACMDBG_H("finished delete default v6 RT rules\n "); + } - /* delete default v6 RT rule */ - if (ip_type != IPA_IP_v4) + /* check software routing fl rule hdl */ + if (softwarerouting_act == true) + { + if(m_is_sta_mode == Q6_MHI_WAN) { - IPACMDBG_H("Delete default v6 routing rules\n"); - /* May have multiple ipv6 iface-routing rules*/ - for (i = 0; i < 2*num_dft_rt_v6; i++) - { - if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) - { - IPACMERR("Routing rule deletion failed!\n"); - res = IPACM_FAILURE; - goto fail; - } - } - IPACMDBG_H("finished delete default v6 RT rules\n "); + handle_software_routing_disable(true); } + else + { + handle_software_routing_disable(false); + } + } + + if(m_is_sta_mode != Q6_MHI_WAN) + { /* clean wan-client header, routing rules */ IPACMDBG_H("left %d wan clients need to be deleted \n ", num_wan_client); for (i = 0; i < num_wan_client; i++) @@ -5397,18 +5489,6 @@ int IPACM_Wan::handle_down_evt() /* free the edm clients cache */ IPACMDBG_H("Free wan clients cache\n"); - /* check software routing fl rule hdl */ - if (softwarerouting_act == true) - { - if(m_is_sta_mode == Q6_MHI_WAN) - { - handle_software_routing_disable(true); - } - else - { - handle_software_routing_disable(false); - } - } /* free dft ipv4 filter rule handlers if any */ if (ip_type != IPA_IP_v6 && rx_prop != NULL) { @@ -5544,8 +5624,13 @@ int IPACM_Wan::handle_down_evt_ex() goto fail; } +#ifndef IPA_MTU_EVENT_MAX /* reset the mtu size */ - mtu_size = DEFAULT_MTU_SIZE; + mtu_v4 = DEFAULT_MTU_SIZE; + mtu_v4_set = false; + mtu_v6 = DEFAULT_MTU_SIZE; + mtu_v6_set = false; +#endif if(ip_type == IPA_IP_v4) { @@ -6110,7 +6195,7 @@ fail: /* handle STA WAN-client */ /* handle WAN client initial, construct full headers (tx property) */ -int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) +int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr, bool replaced, int entry) { #define WAN_IFACE_INDEX_LEN 2 @@ -6122,38 +6207,41 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) uint32_t cnt; int clnt_indx; - clnt_indx = get_wan_client_index(mac_addr); + IPACMDBG_H("WAN client number: %d\n", num_wan_client); - if (clnt_indx != IPACM_INVALID_INDEX) + if(!replaced) { - IPACMERR("eth client is found/attached already with index %d \n", clnt_indx); - return IPACM_FAILURE; - } + clnt_indx = get_wan_client_index(mac_addr); - /* add header to IPA */ - if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS) - { - IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS); - return IPACM_FAILURE; - } + if (clnt_indx != IPACM_INVALID_INDEX) + { + IPACMERR("eth client is found/attached already with index %d \n", clnt_indx); + return IPACM_FAILURE; + } - IPACMDBG_H("WAN client number: %d\n", num_wan_client); + /* add header to IPA */ + if (num_wan_client >= IPA_MAX_NUM_WAN_CLIENTS) + { + IPACMERR("Reached maximum number(%d) of eth clients\n", IPA_MAX_NUM_WAN_CLIENTS); + return IPACM_FAILURE; + } - memcpy(get_client_memptr(wan_client, num_wan_client)->mac, + memcpy(get_client_memptr(wan_client, num_wan_client)->mac, mac_addr, sizeof(get_client_memptr(wan_client, num_wan_client)->mac)); - IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + IPACMDBG_H("Received Client MAC %02x:%02x:%02x:%02x:%02x:%02x\n", mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5]); - IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", + IPACMDBG_H("stored MAC %02x:%02x:%02x:%02x:%02x:%02x\n", get_client_memptr(wan_client, num_wan_client)->mac[0], get_client_memptr(wan_client, num_wan_client)->mac[1], get_client_memptr(wan_client, num_wan_client)->mac[2], get_client_memptr(wan_client, num_wan_client)->mac[3], get_client_memptr(wan_client, num_wan_client)->mac[4], get_client_memptr(wan_client, num_wan_client)->mac[5]); + } /* add header to IPA */ if(tx_prop != NULL) @@ -6254,13 +6342,23 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) goto fail; } - get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; - IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", + if (!replaced) + { + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", num_wan_client, pHeaderDescriptor->hdr[0].name, get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v4); get_client_memptr(wan_client, num_wan_client)->ipv4_header_set=true; - + } else + { + get_client_memptr(wan_client, entry)->hdr_hdl_v4 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("replaced eth-client(%d) v4 full header name:%s header handle:(0x%x)\n", + entry, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wan_client, entry)->hdr_hdl_v4); + get_client_memptr(wan_client, entry)->ipv4_header_set=true; + } break; } } @@ -6350,24 +6448,45 @@ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) goto fail; } - get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; - IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", + if (!replaced) + { + get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", num_wan_client, pHeaderDescriptor->hdr[0].name, get_client_memptr(wan_client, num_wan_client)->hdr_hdl_v6); - get_client_memptr(wan_client, num_wan_client)->ipv6_header_set=true; + } + else + { + get_client_memptr(wan_client, entry)->hdr_hdl_v6 = pHeaderDescriptor->hdr[0].hdr_hdl; + IPACMDBG_H("replaced eth-client(%d) v6 full header name:%s header handle:(0x%x)\n", + entry, + pHeaderDescriptor->hdr[0].name, + get_client_memptr(wan_client, entry)->hdr_hdl_v6); + get_client_memptr(wan_client, entry)->ipv6_header_set=true; + } break; } } /* initialize wifi client*/ - get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false; - get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0; - get_client_memptr(wan_client, num_wan_client)->ipv4_set = false; - get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0; - num_wan_client++; + if (!replaced) + { + get_client_memptr(wan_client, num_wan_client)->route_rule_set_v4 = false; + get_client_memptr(wan_client, num_wan_client)->route_rule_set_v6 = 0; + get_client_memptr(wan_client, num_wan_client)->ipv4_set = false; + get_client_memptr(wan_client, num_wan_client)->ipv6_set = 0; + num_wan_client++; + } + else + { + get_client_memptr(wan_client, entry)->route_rule_set_v4 = false; + get_client_memptr(wan_client, entry)->route_rule_set_v6 = 0; + get_client_memptr(wan_client, entry)->ipv4_set = false; + get_client_memptr(wan_client, entry)->ipv6_set = 0; + } header_name_count++; //keep increasing header_name_count res = IPACM_SUCCESS; IPACMDBG_H("eth client number: %d\n", num_wan_client); @@ -7342,10 +7461,10 @@ fail: rt_rule_entry = &rt_rule->rules[0]; rt_rule_entry->at_rear = false; rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; - rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = ipv6_addr[num_dft_rt_v6][0]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = ipv6_addr[num_dft_rt_v6][1]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = ipv6_addr[num_dft_rt_v6][2]; - rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = ipv6_addr[num_dft_rt_v6][3]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = ipv6_addr[i][0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = ipv6_addr[i][1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = ipv6_addr[i][2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = ipv6_addr[i][3]; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[0] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[1] = 0xFFFFFFFF; rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; @@ -7919,11 +8038,126 @@ int IPACM_Wan::query_mtu_size() return IPACM_FAILURE; } IPACMDBG_H("mtu=[%d]\n", if_mtu.ifr_mtu); - if (if_mtu.ifr_mtu < DEFAULT_MTU_SIZE) { - mtu_size = if_mtu.ifr_mtu; - IPACMDBG_H("replaced mtu=[%d] for (%s)\n", mtu_size, dev_name); + if (if_mtu.ifr_mtu <= DEFAULT_MTU_SIZE) { + mtu_v4 = mtu_v6 = if_mtu.ifr_mtu; + }else { + mtu_v4 = mtu_v6 = DEFAULT_MTU_SIZE; } + IPACMDBG_H("Updated mtu=[%d] for (%s)\n", mtu_v4, dev_name); close(fd); return IPACM_SUCCESS; } + +/* construct complete ethernet header */ +int IPACM_Wan::handle_gw_mac_renew(ipacm_event_data_all *data, int index_client) +{ + int index = IPACM_INVALID_INDEX; + + /* checking if client has same ipv4, v6 will put future work */ + if (data->iptype == IPA_IP_v4) + { + index = get_wan_client_index_ipv4(data->ipv4_addr); + if (index != IPACM_INVALID_INDEX) + { + IPACMDBG_H("Matched client index: %d\n", index); + IPACMDBG_H("Client MAC in cache %02x:%02x:%02x:%02x:%02x:%02x\n", + get_client_memptr(wan_client, index)->mac[0], + get_client_memptr(wan_client, index)->mac[1], + get_client_memptr(wan_client, index)->mac[2], + get_client_memptr(wan_client, index)->mac[3], + get_client_memptr(wan_client, index)->mac[4], + get_client_memptr(wan_client, index)->mac[5]); + + /* check mac same or not */ + if ((data->mac_addr[0] == get_client_memptr(wan_client, index)->mac[0]) && + (data->mac_addr[1] == get_client_memptr(wan_client, index)->mac[1]) && + (data->mac_addr[2] == get_client_memptr(wan_client, index)->mac[2]) && + (data->mac_addr[3] == get_client_memptr(wan_client, index)->mac[3]) && + (data->mac_addr[4] == get_client_memptr(wan_client, index)->mac[4]) && + (data->mac_addr[5] == get_client_memptr(wan_client, index)->mac[5])) + { + IPACMDBG_H(" No need client (%d) mac renew with IPv4 (0x%x)\n", index, data->ipv4_addr); + return IPACM_FAILURE; + } + else + { + IPACMDBG_H(" client %d need mac renew with IPv4 (0x%x)\n", index, data->ipv4_addr); + + /* Del NAT rules before ipv4 RT rules are delete */ + if(get_client_memptr(wan_client, index)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, index)->v4_addr); + CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, index)->v4_addr); + } + + /* clean up STA header / routing rule */ + if (data->ipv4_addr == wan_v4_addr_gw && active_v4) + { + handle_route_del_evt(IPA_IP_v4, true); + IPACMDBG_H("Delete default v4 routing rules\n"); + hdr_hdl_sta_v4 = 0; + header_set_v4 = false; + header_partial_default_wan_v4 = true; + + if (active_v6) + { + handle_route_del_evt(IPA_IP_v6, true); + IPACMDBG_H("Delete default v6 routing rules\n"); + header_partial_default_wan_v6 = true; + } + hdr_hdl_sta_v6 = 0; + header_set_v6 = false; + } + + /* clean up client header routing rule entry */ + if(delete_wan_rtrules(index, IPA_IP_v4)) + { + IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", index); + return IPACM_FAILURE; + } + + get_client_memptr(wan_client, index)->route_rule_set_v4 = false; + get_client_memptr(wan_client, index)->ipv4_set = false; + + IPACMDBG_H("Delete client %d header\n", index); + if(get_client_memptr(wan_client, index)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, index)->hdr_hdl_v4) == false) + { + IPACMERR("unable to delete client v4 header for index %d\n", index); + return IPACM_FAILURE; + } + get_client_memptr(wan_client, index)->ipv4_header_set = false; + } + + if(delete_wan_rtrules(index, IPA_IP_v6)) + { + IPACMERR("unbale to delete wan-client v6 route rules for index %d\n", index); + return IPACM_FAILURE; + } + get_client_memptr(wan_client, index)->route_rule_set_v6 = 0; + get_client_memptr(wan_client, index)->ipv6_set = 0; + if(get_client_memptr(wan_client, index)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, index)->hdr_hdl_v6) == false) + { + IPACMERR("unable to delete client v6 header for index %d\n", index); + return IPACM_FAILURE; + } + get_client_memptr(wan_client, index)->ipv6_header_set = false; + } + /* replacing the old mac to new_mac on same entry */ + get_client_memptr(wan_client, index)->mac[0] = data->mac_addr[0]; + get_client_memptr(wan_client, index)->mac[1] = data->mac_addr[1]; + get_client_memptr(wan_client, index)->mac[2] = data->mac_addr[2]; + get_client_memptr(wan_client, index)->mac[3] = data->mac_addr[3]; + get_client_memptr(wan_client, index)->mac[4] = data->mac_addr[4]; + get_client_memptr(wan_client, index)->mac[5] = data->mac_addr[5]; + index_client = index; + return IPACM_SUCCESS; + } + } + } + return IPACM_FAILURE; +} diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp index 689cc78..eeb4b01 100644 --- a/ipacm/src/IPACM_Wlan.cpp +++ b/ipacm/src/IPACM_Wlan.cpp @@ -562,25 +562,6 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if(ipa_interface_index == ipa_if_num) { IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n"); -#ifdef FEATURE_IPA_ANDROID - if (IPACM_Wan::isXlat() && (data->prefix.iptype == IPA_IP_v4)) - { - /* indicate v4-offload */ - IPACM_OffloadManager::num_offload_v4_tethered_iface++; - IPACMDBG_H("in xlat: update num_offload_v4_tethered_iface %d\n", IPACM_OffloadManager::num_offload_v4_tethered_iface); - - /* xlat not support for 2st tethered iface */ - if (IPACM_OffloadManager::num_offload_v4_tethered_iface > 1) - { - IPACMDBG_H("Not support 2st downstream iface %s for xlat, cur: %d\n", dev_name, - IPACM_OffloadManager::num_offload_v4_tethered_iface); - return; - } - } - - IPACMDBG_H(" support downstream iface %s, cur %d\n", dev_name, - IPACM_OffloadManager::num_offload_v4_tethered_iface); -#endif if(data->prefix.iptype < IPA_IP_MAX && is_downstream_set[data->prefix.iptype] == false) { IPACMDBG_H("Add downstream for IP iptype %d.\n", data->prefix.iptype); @@ -651,6 +632,35 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) } break; } +#ifdef IPA_MTU_EVENT_MAX + case IPA_MTU_UPDATE: + { + IPACMDBG_H("Received IPA_MTU_UPDATE"); + ipacm_event_mtu_info *evt_data = (ipacm_event_mtu_info *)param; + ipa_mtu_info *data = &(evt_data->mtu_info); + + /* IPA_IP_MAX means both ipv4 and ipv6 */ + if ((data->ip_type == IPA_IP_v4 || data->ip_type == IPA_IP_MAX) && IPACM_Wan::isWanUP(ipa_if_num)) + { + handle_private_subnet_android(IPA_IP_v4); + } + + /* IPA_IP_MAX means both ipv4 and ipv6 */ + if ((data->ip_type == IPA_IP_v6 || data->ip_type == IPA_IP_MAX) && IPACM_Wan::isWanUP_V6(ipa_if_num)) + { + //check if the prefix + MTU rules are installed + if (ipv6_prefix_flt_rule_hdl[0] && ipv6_prefix_flt_rule_hdl[1]) { + modify_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); + } + else + { + IPACMERR("failed to update prefix MTU rules, no prefix rules set"); + } + } + } + break; +#endif + #else case IPA_HANDLE_WAN_UP: IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); diff --git a/ipacm_vendor_product.mk b/ipacm_vendor_product.mk index 9fe88b1..f225a30 100644 --- a/ipacm_vendor_product.mk +++ b/ipacm_vendor_product.mk @@ -11,12 +11,20 @@ ifneq ($(TARGET_USES_QMAA_OVERRIDE_DATA),true) endif #TARGET_USES_QMAA_OVERRIDE_DATA endif #TARGET_USES_QMAA +BOARD_IPA_LOW_RAM_EXCP_LIST := bengal + +ifeq ($(TARGET_HAS_LOW_RAM),true) +ifneq ($(call is-board-platform-in-list,$(BOARD_IPA_LOW_RAM_EXCP_LIST)),true) + TARGET_DISABLE_IPACM := true +endif +endif + ifneq ($(TARGET_DISABLE_IPACM),true) -ifneq ($(TARGET_HAS_LOW_RAM),true) BOARD_PLATFORM_LIST := msm8909 BOARD_PLATFORM_LIST += msm8916 BOARD_PLATFORM_LIST += msm8917 BOARD_PLATFORM_LIST += qm215 +BOARD_PLATFORM_LIST += msm8937 BOARD_IPAv3_LIST := msm8998 BOARD_IPAv3_LIST += sdm845 BOARD_IPAv3_LIST += sdm710 @@ -40,4 +48,3 @@ endif # $(TARGET_ARCH) endif endif endif -endif
\ No newline at end of file |