diff options
author | ChengYou Ho <chengyouho@google.com> | 2019-12-23 16:59:59 +0800 |
---|---|---|
committer | Wilson Sung <wilsonsung@google.com> | 2020-02-03 13:33:21 +0800 |
commit | dc455fa6e93bcb5a252747bed3941759ce247c38 (patch) | |
tree | a889a4367664513ff539f6556fe7aa9857ec2079 /ipacm | |
parent | 6bafc1497f181945305cba34f8b2f2ddac35b650 (diff) | |
parent | 3ba31701681587a2aba85ad4fed3b0d48e265fd0 (diff) | |
download | ipacfg-mgr-dc455fa6e93bcb5a252747bed3941759ce247c38.tar.gz |
Merge remote-tracking branch 'goog/qcom/release/LA.UM.8.1.C9.09.00.00.518.343'
Bug: 146759211
Change-Id: I7e90b1f60353762b17bf0d1f5583767644cea12f
Diffstat (limited to 'ipacm')
-rw-r--r-- | ipacm/inc/IPACM_Config.h | 5 | ||||
-rw-r--r-- | ipacm/inc/IPACM_ConntrackListener.h | 4 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Conntrack_NATApp.h | 12 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Defs.h | 21 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Filtering.h | 12 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Iface.h | 10 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Lan.h | 23 | ||||
-rw-r--r-- | ipacm/inc/IPACM_OffloadManager.h | 4 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Routing.h | 4 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Wan.h | 91 | ||||
-rw-r--r-- | ipacm/inc/IPACM_Wlan.h | 20 | ||||
-rw-r--r-- | ipacm/src/Android.mk | 20 | ||||
-rw-r--r-- | ipacm/src/IPACM_Config.cpp | 4 | ||||
-rw-r--r-- | ipacm/src/IPACM_ConntrackListener.cpp | 14 | ||||
-rw-r--r-- | ipacm/src/IPACM_Conntrack_NATApp.cpp | 298 | ||||
-rw-r--r-- | ipacm/src/IPACM_Filtering.cpp | 459 | ||||
-rw-r--r-- | ipacm/src/IPACM_Iface.cpp | 296 | ||||
-rw-r--r-- | ipacm/src/IPACM_IfaceManager.cpp | 1 | ||||
-rw-r--r-- | ipacm/src/IPACM_Lan.cpp | 495 | ||||
-rw-r--r-- | ipacm/src/IPACM_Main.cpp | 99 | ||||
-rw-r--r-- | ipacm/src/IPACM_OffloadManager.cpp | 169 | ||||
-rw-r--r-- | ipacm/src/IPACM_Routing.cpp | 109 | ||||
-rw-r--r-- | ipacm/src/IPACM_Wan.cpp | 2405 | ||||
-rw-r--r-- | ipacm/src/IPACM_Wlan.cpp | 273 | ||||
-rw-r--r-- | ipacm/src/IPACM_Xml.cpp | 13 |
25 files changed, 4093 insertions, 768 deletions
diff --git a/ipacm/inc/IPACM_Config.h b/ipacm/inc/IPACM_Config.h index af1b616..9230f7d 100644 --- a/ipacm/inc/IPACM_Config.h +++ b/ipacm/inc/IPACM_Config.h @@ -147,6 +147,11 @@ public: bool isMCC_Mode; + /* IPA_HW_FNR_STATS */ + bool hw_fnr_stats_support; + int hw_counter_offset; + int sw_counter_offset; + /* To return the instance */ static IPACM_Config* GetInstance(); diff --git a/ipacm/inc/IPACM_ConntrackListener.h b/ipacm/inc/IPACM_ConntrackListener.h index d965cf7..24a2c72 100644 --- a/ipacm/inc/IPACM_ConntrackListener.h +++ b/ipacm/inc/IPACM_ConntrackListener.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -103,7 +103,7 @@ private: public: char wan_ifname[IPA_IFACE_NAME_LEN]; uint32_t wan_ipaddr; - bool isStaMode; + ipacm_wan_iface_type backhaul_mode; IPACM_ConntrackListener(); void event_callback(ipa_cm_event_id, void *data); inline bool isWanUp() diff --git a/ipacm/inc/IPACM_Conntrack_NATApp.h b/ipacm/inc/IPACM_Conntrack_NATApp.h index c3749e1..b362907 100644 --- a/ipacm/inc/IPACM_Conntrack_NATApp.h +++ b/ipacm/inc/IPACM_Conntrack_NATApp.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -65,6 +65,8 @@ typedef struct _nat_table_entry bool enabled; uint32_t rule_hdl; + /* used for pcie-modem */ + uint32_t rule_id; }nat_table_entry; #define CHK_TBL_HDL() if(nat_table_hdl == 0){ return -1; } @@ -80,6 +82,8 @@ private: uint32_t pub_ip_addr; uint32_t pub_ip_addr_pre; uint32_t nat_table_hdl; + /* used for pcie-modem */ + uint8_t pub_mux_id; int curCnt, max_entries; @@ -94,7 +98,10 @@ private: struct nf_conntrack *ct; struct nfct_handle *ct_hdl; + int m_fd_ipa; + NatApp(); + ~NatApp(); int Init(); void UpdateCTUdpTs(nat_table_entry *, uint32_t); @@ -114,6 +121,9 @@ public: int AddEntry(const nat_table_entry *); int DeleteEntry(const nat_table_entry *); + int AddConnection(const nat_table_entry *); + int DelConnection(const uint32_t); + void UpdateUDPTimeStamp(); int UpdatePwrSaveIf(uint32_t); diff --git a/ipacm/inc/IPACM_Defs.h b/ipacm/inc/IPACM_Defs.h index d2186b6..65d5ce4 100644 --- a/ipacm/inc/IPACM_Defs.h +++ b/ipacm/inc/IPACM_Defs.h @@ -122,6 +122,7 @@ extern "C" #define IPA_MAX_NUM_ETH_CLIENTS 15 #define IPA_MAX_NUM_AMPDU_RULE 15 #define IPA_MAC_ADDR_SIZE 6 +#define IPA_MAX_NUM_SW_PDNS 15 /*=========================================================================== GLOBAL DEFINITIONS AND DECLARATIONS @@ -186,7 +187,8 @@ typedef enum IPA_ETH_BRIDGE_CLIENT_ADD, /* ipacm_event_eth_bridge */ IPA_ETH_BRIDGE_CLIENT_DEL, /* ipacm_event_eth_bridge*/ IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, /* ipacm_event_eth_bridge*/ - IPA_SSR_NOTICE, /* NULL*/ + IPA_SSR_NOTICE, /* NULL*/ + IPA_COALESCE_NOTICE, /* NULL*/ #ifdef FEATURE_L2TP IPA_ADD_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */ IPA_DEL_VLAN_IFACE, /* ipa_ioc_vlan_iface_info */ @@ -352,31 +354,34 @@ typedef struct struct ipa_wlan_hdr_attrib_val attribs[0]; } ipacm_event_data_wlan_ex; +typedef enum +{ + Q6_WAN = 0, + WLAN_WAN, + ECM_WAN, + Q6_MHI_WAN +} ipacm_wan_iface_type; + typedef struct _ipacm_event_iface_up { + ipacm_wan_iface_type backhaul_type; char ifname[IPA_IFACE_NAME_LEN]; uint32_t ipv4_addr; uint32_t addr_mask; uint32_t ipv6_prefix[2]; - bool is_sta; uint8_t xlat_mux_id; uint8_t mux_id; }ipacm_event_iface_up; typedef struct _ipacm_event_iface_up_tether { + ipacm_wan_iface_type backhaul_type; uint32_t if_index_tether; uint32_t ipv6_prefix[2]; bool is_sta; uint8_t xlat_mux_id; }ipacm_event_iface_up_tehter; -typedef enum -{ - Q6_WAN = 0, - WLAN_WAN, - ECM_WAN -} ipacm_wan_iface_type; typedef struct _ipacm_ifacemgr_data { diff --git a/ipacm/inc/IPACM_Filtering.h b/ipacm/inc/IPACM_Filtering.h index 9bb8247..428c21a 100644 --- a/ipacm/inc/IPACM_Filtering.h +++ b/ipacm/inc/IPACM_Filtering.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -47,6 +47,8 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <IPACM_Defs.h> #include <linux/rmnet_ipa_fd_ioctl.h> +#define IPA_PCIE_MODEM_RULE_ID_START 69 + class IPACM_Filtering { public: @@ -54,6 +56,10 @@ public: ~IPACM_Filtering(); bool AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTable); bool AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable); +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + bool AddFilteringRule_hw_index(struct ipa_ioc_add_flt_rule *ruleTable, int hw_counter_index); + bool AddFilteringRuleAfter_hw_index(struct ipa_ioc_add_flt_rule_after *ruleTable, int hw_counter_index); +#endif //IPA_IOCTL_SET_FNR_COUNTER_INFO bool DeleteFilteringRule(struct ipa_ioc_del_flt_rule *ruleTable); bool Commit(enum ipa_ip_type ip); bool Reset(enum ipa_ip_type ip); @@ -63,6 +69,8 @@ public: uint8_t num_rules); bool AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *rule_table_v4, struct ipa_ioc_add_flt_rule const * rule_table_v6, uint8_t mux_id); + bool AddOffloadFilteringRule(struct ipa_ioc_add_flt_rule *flt_rule_tbl, uint8_t mux_id, uint8_t default_path); + bool DelOffloadFilteringRule(struct ipa_ioc_del_flt_rule const *flt_rule_tbl); bool SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table); bool ModifyFilteringRule(struct ipa_ioc_mdfy_flt_rule* ruleTable); ipa_filter_action_enum_v01 GetQmiFilterAction(ipa_flt_action action); @@ -70,6 +78,8 @@ public: private: static const char *DEVICE_NAME; int fd; /* File descriptor of the IPA device node /dev/ipa */ + int total_num_offload_rules; + int pcie_modem_rule_id; }; #endif //IPACM_FILTERING_H diff --git a/ipacm/inc/IPACM_Iface.h b/ipacm/inc/IPACM_Iface.h index a562613..55d9e99 100644 --- a/ipacm/inc/IPACM_Iface.h +++ b/ipacm/inc/IPACM_Iface.h @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -139,13 +139,17 @@ public: static IPACM_Filtering m_filtering; static IPACM_Header m_header; + void change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib); + /* software routing enable */ - virtual int handle_software_routing_enable(void); + virtual int handle_software_routing_enable(bool mhip); /* software routing disable */ - virtual int handle_software_routing_disable(void); + virtual int handle_software_routing_disable(bool mhip); void delete_iface(void); + bool is_global_ipv6_addr(uint32_t* ipv6_addr); + private: static const char *DEVICE_NAME; diff --git a/ipacm/inc/IPACM_Lan.h b/ipacm/inc/IPACM_Lan.h index 700dfbc..bf815c5 100644 --- a/ipacm/inc/IPACM_Lan.h +++ b/ipacm/inc/IPACM_Lan.h @@ -49,6 +49,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "IPACM_Filtering.h" #include "IPACM_Config.h" #include "IPACM_Conntrack_NATApp.h" +#include "IPACM_Wan.h" #define IPA_WAN_DEFAULT_FILTER_RULE_HANDLES 1 #define IPA_PRIV_SUBNET_FILTER_RULE_HANDLES 3 @@ -94,6 +95,8 @@ typedef struct _ipa_eth_client int ipv6_set; bool ipv4_header_set; bool ipv6_header_set; + /* used for pcie-modem */ + uint32_t v6_rt_rule_id[IPV6_NUM_ADDR]; eth_client_rt_hdl eth_rt_hdl[0]; /* depends on number of tx properties */ }ipa_eth_client; @@ -121,10 +124,10 @@ public: virtual int handle_wan_up_ex(ipacm_ext_prop* ext_prop, ipa_ip_type iptype, uint8_t xlat_mux_id); /* delete filter rule for wan_down event*/ - virtual int handle_wan_down(bool is_sta_mode); + virtual int handle_wan_down(ipacm_wan_iface_type backhaul_mode); /* delete filter rule for wan_down event*/ - virtual int handle_wan_down_v6(bool is_sta_mode); + virtual int handle_wan_down_v6(ipacm_wan_iface_type backhaul_mode); /* configure private subnet filter rules*/ virtual int handle_private_subnet(ipa_ip_type iptype); @@ -393,6 +396,18 @@ private: { for(num_v6 =0;num_v6 < get_client_memptr(eth_client, clt_indx)->route_rule_set_v6;num_v6++) { + /* send client-v6 delete to pcie modem only with global ipv6 with tx_index = 1 one time*/ + if(is_global_ipv6_addr(get_client_memptr(eth_client, clt_indx)->v6_addr[num_v6]) && (IPACM_Wan::backhaul_mode == Q6_MHI_WAN) + && (get_client_memptr(eth_client, clt_indx)->v6_rt_rule_id[num_v6] > 0)) + { + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for rule-id:%d\n", clt_indx,num_v6, + get_client_memptr(eth_client, clt_indx)->v6_rt_rule_id[num_v6]); + if (del_connection(clt_indx, num_v6)) + { + IPACMERR("PCIE filter rule deletion failed! (%d-client) %d v6-entry\n",clt_indx, num_v6); + } + } + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); rt_hdl = get_client_memptr(eth_client, clt_indx)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6[num_v6]; if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) @@ -445,6 +460,10 @@ private: /*handle reset usb-client rt-rules */ int handle_lan_client_reset_rt(ipa_ip_type iptype); + + /* for pcie modem */ + virtual int add_connection(int client_index, int v6_num); + virtual int del_connection(int client_index, int v6_num); }; #endif /* IPACM_LAN_H */ diff --git a/ipacm/inc/IPACM_OffloadManager.h b/ipacm/inc/IPACM_OffloadManager.h index 88a411b..8ac904f 100644 --- a/ipacm/inc/IPACM_OffloadManager.h +++ b/ipacm/inc/IPACM_OffloadManager.h @@ -86,7 +86,7 @@ public: virtual RET getStats(const char * /* upstream */, bool /* reset */, OffloadStatistics& /* ret */); - static IPACM_OffloadManager *pInstance; //sky + static IPACM_OffloadManager *pInstance; IpaEventListener *elrInstance; @@ -96,6 +96,8 @@ public: bool push_framework_event(const char * if_name, _ipacm_offload_prefix prefix); + static int num_offload_v4_tethered_iface; + private: std::list<std::string> valid_ifaces; diff --git a/ipacm/inc/IPACM_Routing.h b/ipacm/inc/IPACM_Routing.h index b5ffabc..663076b 100644 --- a/ipacm/inc/IPACM_Routing.h +++ b/ipacm/inc/IPACM_Routing.h @@ -55,6 +55,10 @@ public: ~IPACM_Routing(); bool AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable); + +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + bool AddRoutingRule_hw_index(struct ipa_ioc_add_rt_rule *ruleTable, int hw_counter_index); +#endif //IPA_IOCTL_SET_FNR_COUNTER_INFO bool DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable); bool Commit(enum ipa_ip_type ip); diff --git a/ipacm/inc/IPACM_Wan.h b/ipacm/inc/IPACM_Wan.h index 1b917c6..684bfb7 100644 --- a/ipacm/inc/IPACM_Wan.h +++ b/ipacm/inc/IPACM_Wan.h @@ -89,6 +89,12 @@ typedef struct _ipa_wan_client wan_client_rt_hdl wan_rt_hdl[0]; /* depends on number of tx properties */ }ipa_wan_client; +typedef struct +{ + bool coalesce_tcp_enable; + bool coalesce_udp_enable; +}ipacm_coalesce; + /* wan iface */ class IPACM_Wan : public IPACM_Iface { @@ -215,15 +221,48 @@ public: return IPACM_SUCCESS; } #endif + static void coalesce_config(uint8_t qmap_id, bool tcp_enable, bool udp_enable) + { + if (qmap_id >= IPA_MAX_NUM_SW_PDNS) + { + IPACMERR("qmap_id (%d) beyond the Max range (%d), abort\n", + qmap_id, IPA_MAX_NUM_SW_PDNS); + return ; + } + + IPACM_Wan::coalesce_enable_info[qmap_id].coalesce_tcp_enable = tcp_enable; + IPACM_Wan::coalesce_enable_info[qmap_id].coalesce_udp_enable = udp_enable; + IPACMDBG_H(" Updated qmap(%d) coalesce enable TCP:%d UDP:%d\n", + qmap_id, + IPACM_Wan::coalesce_enable_info[qmap_id].coalesce_tcp_enable, + IPACM_Wan::coalesce_enable_info[qmap_id].coalesce_udp_enable); + return ; + } + + static void coalesce_config_reset() + { + int i; + /* reset coalesce settings on all modem interfaces */ + for (i = 0; i < IPA_MAX_NUM_SW_PDNS; i++) + IPACM_Wan::coalesce_config(i, false, false); + return ; + } static uint32_t getWANIP() { return curr_wan_ip; } - static bool getXlat_Mux_Id() + static int getXlat_Mux_Id() { - return xlat_mux_id; + if (is_xlat) + { + IPACMDBG_H("xlat_mux_id: %d\n", xlat_mux_id); + return xlat_mux_id; + } else { + IPACMDBG_H("no xlat return invalid mux-id: 0\n"); + return 0; + } } static void clearExtProp() @@ -243,12 +282,13 @@ public: static int num_v6_flt_rule; ipacm_wan_iface_type m_is_sta_mode; - static bool backhaul_is_sta_mode; + static ipacm_wan_iface_type backhaul_mode; static bool is_ext_prop_set; static uint32_t backhaul_ipv6_prefix[2]; static bool embms_is_on; static bool backhaul_is_wan_bridge; + static bool is_xlat; static bool isWan_Bridge_Mode() { @@ -260,8 +300,16 @@ public: static int ipa_if_num_tether_v4[IPA_MAX_IFACE_ENTRIES]; static uint32_t ipa_if_num_tether_v6_total; static int ipa_if_num_tether_v6[IPA_MAX_IFACE_ENTRIES]; + + static bool isXlat() + { + return is_xlat; + } #endif + /* indicate coalesce support on tcp or udp*/ + static ipacm_coalesce coalesce_enable_info[IPA_MAX_NUM_SW_PDNS]; + private: bool is_ipv6_frag_firewall_flt_rule_installed; @@ -292,6 +340,8 @@ private: bool header_partial_default_wan_v6; uint8_t ext_router_mac_addr[IPA_MAC_ADDR_SIZE]; uint8_t netdev_mac[IPA_MAC_ADDR_SIZE]; + /* create additional set of v4 Coalesce RT-rules: tcp udp */ + uint32_t dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+ 2*MAX_DEFAULT_v6_ROUTE_RULES]; static int num_ipv4_modem_pdn; @@ -314,13 +364,25 @@ private: int header_name_count; uint32_t num_wan_client; uint8_t invalid_mac[IPA_MAC_ADDR_SIZE]; - bool is_xlat; + bool is_xlat_local; /* update network stats for CNE */ int ipa_network_stats_fd; uint32_t hdr_hdl_dummy_v6; uint32_t hdr_proc_hdl_dummy_v6; + /* handle for UDP mhi frag rule */ + uint32_t mhi_dl_v4_frag_hdl; + + /* handle for icmpv6 exception rule */ + uint32_t icmpv6_exception_hdl; + + /* handle for TCP FIN rule */ + uint32_t tcp_fin_hdl; + + /* handle for TCP RST rule */ + uint32_t tcp_rst_hdl; + inline ipa_wan_client* get_client_memptr(ipa_wan_client *param, int cnt) { char *ret = ((char *)param) + (wan_client_len * cnt); @@ -506,6 +568,9 @@ private: /* handle new_address event */ int handle_addr_evt(ipacm_event_data_addr *data); + /* handle new_address event for q6_mhi */ + 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); @@ -562,10 +627,6 @@ private: int install_wan_filtering_rule(bool is_sw_routing); - void change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib); - - bool is_global_ipv6_addr(uint32_t* ipv6_addr); - void handle_wlan_SCC_MCC_switch(bool, ipa_ip_type); void handle_wan_client_SCC_MCC_switch(bool, ipa_ip_type); @@ -578,6 +639,20 @@ private: /* construct dummy ethernet header */ int add_dummy_rx_hdr(); + + int handle_coalesce_evt(); + + int add_offload_frag_rule(); + + int delete_offload_frag_rule(); + + int add_icmpv6_exception_rule(); + + int delete_icmpv6_exception_rule(); + + int add_tcp_fin_rst_exception_rule(); + + int delete_tcp_fin_rst_exception_rule(); }; #endif /* IPACM_WAN_H */ diff --git a/ipacm/inc/IPACM_Wlan.h b/ipacm/inc/IPACM_Wlan.h index f3c6d65..9c828ee 100644 --- a/ipacm/inc/IPACM_Wlan.h +++ b/ipacm/inc/IPACM_Wlan.h @@ -54,6 +54,7 @@ typedef struct _wlan_client_rt_hdl uint32_t wifi_rt_rule_hdl_v4; uint32_t wifi_rt_rule_hdl_v6[IPV6_NUM_ADDR]; uint32_t wifi_rt_rule_hdl_v6_wan[IPV6_NUM_ADDR]; + }wlan_client_rt_hdl; typedef struct _ipa_wlan_client @@ -72,6 +73,8 @@ typedef struct _ipa_wlan_client bool ipv6_header_set; bool power_save_set; enum ipa_client_type wigig_ipa_client; + /* used for pcie-modem */ + uint32_t v6_rt_rule_id[IPV6_NUM_ADDR]; wlan_client_rt_hdl wifi_rt_hdl[0]; /* depends on number of tx properties */ }ipa_wlan_client; @@ -185,6 +188,18 @@ private: { for(num_v6 =0;num_v6 < get_client_memptr(wlan_client, clt_indx)->route_rule_set_v6;num_v6++) { + /* send client-v6 delete to pcie modem only with global ipv6 with tx_index = 0 one time*/ + if(is_global_ipv6_addr(get_client_memptr(wlan_client, clt_indx)->v6_addr[num_v6]) && (IPACM_Wan::backhaul_mode == Q6_MHI_WAN) + && (get_client_memptr(wlan_client, clt_indx)->v6_rt_rule_id[num_v6] > 0)) + { + IPACMDBG_H("Delete client index %d ipv6 RT-rules for %d-st ipv6 for rule-id:%d\n", clt_indx,num_v6, + get_client_memptr(wlan_client, clt_indx)->v6_rt_rule_id[num_v6]); + if (del_connection(clt_indx, num_v6)) + { + IPACMERR("PCIE filter rule deletion failed! (%d-client) %d v6-entry\n",clt_indx, num_v6); + } + } + IPACMDBG_H("Delete client index %d ipv6 Qos rules for %d-st ipv6 for tx:%d\n", clt_indx,num_v6,tx_index); rt_hdl = get_client_memptr(wlan_client, clt_indx)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6[num_v6]; if(m_routing.DeleteRoutingHdl(rt_hdl, IPA_IP_v6) == false) @@ -237,6 +252,11 @@ private: void handle_SCC_MCC_switch(ipa_ip_type); + /* for pcie modem */ + int add_connection(int client_index, int v6_num); + + int del_connection(int client_index, int v6_num); + #ifdef FEATURE_IPACM_RESTART /*query wlan-clients */ int ipa_query_wlan_client(); diff --git a/ipacm/src/Android.mk b/ipacm/src/Android.mk index 28c36fc..634308a 100644 --- a/ipacm/src/Android.mk +++ b/ipacm/src/Android.mk @@ -1,6 +1,18 @@ +TARGET_DISABLE_IPACM := false + +ifeq ($(TARGET_USES_QMAA),true) +ifneq ($(TARGET_USES_QMAA_OVERRIDE_DATA),true) + TARGET_DISABLE_IPACM := true +endif #TARGET_USES_QMAA_OVERRIDE_DATA +endif #TARGET_USES_QMAA + + +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_IPAv3_LIST := msm8998 BOARD_IPAv3_LIST += sdm845 BOARD_IPAv3_LIST += sdm710 @@ -10,6 +22,9 @@ BOARD_IPAv3_LIST += $(MSMSTEPPE) BOARD_IPAv3_LIST += $(TRINKET) BOARD_IPAv3_LIST += lito BOARD_IPAv3_LIST += atoll +BOARD_IPAv3_LIST += bengal +BOARD_ETH_BRIDGE_LIST := msmnile +BOARD_ETH_BRIDGE_LIST += kona ifneq ($(call is-board-platform-in-list,$(BOARD_PLATFORM_LIST)),true) ifneq (,$(filter $(QCOM_BOARD_PLATFORMS),$(TARGET_BOARD_PLATFORM))) @@ -27,7 +42,10 @@ LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr LOCAL_CFLAGS := -DFEATURE_IPA_ANDROID LOCAL_CFLAGS += -DFEATURE_IPACM_RESTART + +ifeq ($(call is-board-platform-in-list,$(BOARD_ETH_BRIDGE_LIST)),true) LOCAL_CFLAGS += -DFEATURE_ETH_BRIDGE_LE +endif LOCAL_CFLAGS += -DFEATURE_IPACM_HAL -Wall -Werror -Wno-error=macro-redefined -Wno-enum-compare ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT))) @@ -121,3 +139,5 @@ include $(BUILD_PREBUILT) endif # $(TARGET_ARCH) endif endif +endif +endif
\ No newline at end of file diff --git a/ipacm/src/IPACM_Config.cpp b/ipacm/src/IPACM_Config.cpp index bfacd7c..781f1cb 100644 --- a/ipacm/src/IPACM_Config.cpp +++ b/ipacm/src/IPACM_Config.cpp @@ -143,6 +143,10 @@ IPACM_Config::IPACM_Config() ipa_bridge_enable = false; isMCC_Mode = false; ipa_max_valid_rm_entry = 0; + /* IPA_HW_FNR_STATS */ + hw_fnr_stats_support = false; + hw_counter_offset = 0; + sw_counter_offset = 0; memset(&rt_tbl_default_v4, 0, sizeof(rt_tbl_default_v4)); memset(&rt_tbl_lan_v4, 0, sizeof(rt_tbl_lan_v4)); diff --git a/ipacm/src/IPACM_ConntrackListener.cpp b/ipacm/src/IPACM_ConntrackListener.cpp index d6289e3..e006393 100644 --- a/ipacm/src/IPACM_ConntrackListener.cpp +++ b/ipacm/src/IPACM_ConntrackListener.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -230,7 +230,7 @@ void IPACM_ConntrackListener::HandleNonNatIPAddr( bool NatIface = false; int cnt, ret; - if (isStaMode) + if (backhaul_mode != Q6_WAN) { IPACMDBG("In STA mode, don't add dummy rules for non nat ifaces\n"); return; @@ -368,8 +368,8 @@ void IPACM_ConntrackListener::TriggerWANUp(void *in_param) } WanUp = true; - isStaMode = wanup_data->is_sta; - IPACMDBG("isStaMode: %d\n", isStaMode); + backhaul_mode = wanup_data->backhaul_type; + IPACMDBG("backhaul_mode: %d\n", backhaul_mode); wan_ipaddr = wanup_data->ipv4_addr; memcpy(wan_ifname, wanup_data->ifname, sizeof(wan_ifname)); @@ -730,7 +730,7 @@ bool IPACM_ConntrackListener::AddIface( } } - if (!isStaMode) + if (backhaul_mode == Q6_WAN) { /* check whether non nat iface or not, on Non Nat iface add dummy rule by copying public ip to private ip */ @@ -999,7 +999,7 @@ void IPACM_ConntrackListener::CheckSTAClient( /* Check whether target is in STA client list or not if not ignore the connection */ - if(!isStaMode || (StaClntCnt == 0)) + if((backhaul_mode == Q6_WAN) || (StaClntCnt == 0)) { return; } @@ -1114,7 +1114,7 @@ void IPACM_ConntrackListener::ProcessTCPorUDPMsg( } else { - if (isStaMode) + if (backhaul_mode != Q6_WAN) { IPACMDBG("In STA mode, ignore connections destinated to STA interface\n"); goto IGNORE; diff --git a/ipacm/src/IPACM_Conntrack_NATApp.cpp b/ipacm/src/IPACM_Conntrack_NATApp.cpp index 4004597..c1f47e1 100644 --- a/ipacm/src/IPACM_Conntrack_NATApp.cpp +++ b/ipacm/src/IPACM_Conntrack_NATApp.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -28,6 +28,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "IPACM_Conntrack_NATApp.h" #include "IPACM_ConntrackClient.h" +#include "IPACM_ConntrackListener.h" #ifdef FEATURE_IPACM_HAL #include "IPACM_OffloadManager.h" #endif @@ -47,6 +48,7 @@ NatApp::NatApp() nat_table_hdl = 0; pub_ip_addr = 0; + pub_mux_id = 0; curCnt = 0; @@ -57,6 +59,18 @@ NatApp::NatApp() ct_hdl = NULL; memset(temp, 0, sizeof(temp)); + m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR); + if(m_fd_ipa < 0) + { + IPACMERR("Failed to open %s\n",IPA_DEVICE_NAME); + } +} + +NatApp::~NatApp() +{ + if (m_fd_ipa) { + close(m_fd_ipa); + } } int NatApp::Init(void) @@ -205,6 +219,22 @@ int NatApp::AddTable(uint32_t pub_ip, uint8_t mux_id) continue; } cache[cnt].enabled = true; + /* send connections info to pcie modem only with DL direction */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP)) + { + ret = AddConnection(&cache[cnt]); + if(ret > 0) + { + /* save the rule id for deletion */ + cache[cnt].rule_id = ret; + IPACMDBG_H("rule-id(%d)\n", cache[cnt].rule_id); + } + else + { + IPACMERR("unable to add Connection to pcie modem: error:%d\n", ret); + cache[cnt].rule_id = 0; + } + } IPACMDBG("On wan-iface reset added below rule successfully\n"); iptodot("Private IP", nat_rule.private_ip); @@ -217,24 +247,21 @@ int NatApp::AddTable(uint32_t pub_ip, uint8_t mux_id) } pub_ip_addr = pub_ip; + pub_mux_id = mux_id; + IPACMDBG(" Set pub_mux_id: %d\t", pub_mux_id); return 0; } void NatApp::Reset() { - int cnt = 0; - nat_table_hdl = 0; pub_ip_addr = 0; - /* NAT tbl deleted, reset enabled bit */ - for(cnt = 0; cnt < max_entries; cnt++) - { - cache[cnt].enabled = false; - } + pub_mux_id = 0; } int NatApp::DeleteTable(uint32_t pub_ip) { + int cnt = 0; int ret; IPACMDBG_H("%s() %d\n", __FUNCTION__, __LINE__); @@ -247,6 +274,27 @@ int NatApp::DeleteTable(uint32_t pub_ip) return -1; } + /* NAT tbl deleted, reset enabled bit */ + for(cnt = 0; cnt < max_entries; cnt++) + { + cache[cnt].enabled = false; + /* send connections del info to pcie modem first */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0)) + + { + ret = DelConnection(cache[cnt].rule_id); + if(ret) + { + IPACMERR("unable to del Connection to pcie modem: %d\n", ret); + } + else + { + /* save the rule id for deletion */ + cache[cnt].rule_id = 0; + } + } + } + ret = ipa_nat_del_ipv4_tbl(nat_table_hdl); if(ret) { @@ -286,6 +334,7 @@ bool NatApp::ChkForDup(const nat_table_entry *rule) int NatApp::DeleteEntry(const nat_table_entry *rule) { int cnt = 0; + int ret = 0; IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); log_nat(rule->protocol,rule->private_ip,rule->target_ip,rule->private_port,\ @@ -303,6 +352,21 @@ int NatApp::DeleteEntry(const nat_table_entry *rule) if(cache[cnt].enabled == true) { + /* send connections del info to pcie modem first */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0)) + { + ret = DelConnection(cache[cnt].rule_id); + if(ret) + { + IPACMERR("unable to del Connection to pcie modem: %d\n", ret); + } + else + { + /* save the rule id for deletion */ + cache[cnt].rule_id = 0; + } + } + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) { IPACMERR("%s() %d deletion failed\n", __FUNCTION__, __LINE__); @@ -329,6 +393,7 @@ int NatApp::AddEntry(const nat_table_entry *rule) { int cnt = 0; ipa_nat_ipv4_rule nat_rule; + int ret = 0; IPACMDBG("%s() %d\n", __FUNCTION__, __LINE__); @@ -398,8 +463,23 @@ int NatApp::AddEntry(const nat_table_entry *rule) } cache[cnt].enabled = true; + /* send connections info to pcie modem only with DL direction */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (rule->dst_nat == true || rule->protocol == IPPROTO_TCP)) + { + ret = AddConnection(rule); + if(ret > 0) + { + /* save the rule id for deletion */ + cache[cnt].rule_id = ret; + IPACMDBG_H("rule-id(%d)\n", cache[cnt].rule_id); + } + else + { + IPACMERR("unable to add Connection to pcie modem: error:%d\n", ret); + cache[cnt].rule_id = 0; + } + } } - cache[cnt].private_ip = rule->private_ip; cache[cnt].target_ip = rule->target_ip; cache[cnt].target_port = rule->target_port; @@ -430,6 +510,137 @@ int NatApp::AddEntry(const nat_table_entry *rule) return 0; } +/* Add new entry to the nat table on new connection, return rule-id */ +int NatApp::AddConnection(const nat_table_entry *rule) +{ + int len, res = IPACM_SUCCESS; + ipa_ioc_add_flt_rule *pFilteringTable = NULL; + + /* contruct filter rules to pcie modem */ + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_generate_flt_eq flt_eq; + + IPACMDBG("\n"); + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + + pFilteringTable->commit = 1; + pFilteringTable->global = false; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_rules = (uint8_t)1; + + /* Configuring Software-Routing Filtering Rule */ + 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; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_PORT; + flt_rule_entry.rule.attrib.src_port = rule->target_port; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_PORT; + flt_rule_entry.rule.attrib.dst_port = rule->public_port; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = rule->protocol; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v4.dst_addr = rule->public_ip; + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; + flt_rule_entry.rule.attrib.u.v4.src_addr_mask = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v4.src_addr = rule->target_ip; + IPACMDBG_H("src(0x%x) port(%d)->dst(0x%x) port(%d), protocol(%d) pub_mux_id (%d)\n", + rule->target_ip, rule->target_port, rule->public_ip, rule->public_port, + rule->protocol, pub_mux_id); + + 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_v4; + 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)); + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if(false == IPACM_Iface::m_filtering.AddOffloadFilteringRule(pFilteringTable, pub_mux_id, 0)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + + /* get rule-id */ + res = pFilteringTable->rules[0].flt_rule_hdl; + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int NatApp::DelConnection(const uint32_t rule_id) +{ + int len, res = IPACM_SUCCESS; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + + + struct ipa_flt_rule_del flt_rule_entry; + + IPACMDBG("\n"); + len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_hdls = (uint8_t)1; + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = rule_id; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == IPACM_Iface::m_filtering.DelOffloadFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts) { #ifdef FEATURE_IPACM_HAL @@ -629,7 +840,7 @@ bool NatApp::isPwrSaveIf(uint32_t ip_addr) int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) { - int cnt; + int cnt, ret; IPACMDBG_H("Received IP address: 0x%x\n", client_lan_ip); if(client_lan_ip == INVALID_IP_ADDR) @@ -662,6 +873,21 @@ int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) if(cache[cnt].private_ip == client_lan_ip && cache[cnt].enabled == true) { + /* send connections del info to pcie modem first */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0)) + { + ret = DelConnection(cache[cnt].rule_id); + if(ret) + { + IPACMERR("unable to del Connection to pcie modem: %d\n", ret); + } + else + { + /* save the rule id for deletion */ + cache[cnt].rule_id = 0; + } + } + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) { IPACMERR("unable to delete the rule\n"); @@ -678,7 +904,7 @@ int NatApp::UpdatePwrSaveIf(uint32_t client_lan_ip) int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) { - int cnt; + int cnt, ret; ipa_nat_ipv4_rule nat_rule; IPACMDBG_H("Received ip address: 0x%x\n", client_lan_ip); @@ -721,6 +947,22 @@ int NatApp::ResetPwrSaveIf(uint32_t client_lan_ip) continue; } cache[cnt].enabled = true; + /* send connections info to pcie modem only with DL direction */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP)) + { + ret = AddConnection(&cache[cnt]); + if(ret > 0) + { + /* save the rule id for deletion */ + cache[cnt].rule_id = ret; + IPACMDBG_H("rule-id(%d)\n", cache[cnt].rule_id); + } + else + { + IPACMERR("unable to add Connection to pcie modem: error:%d\n", ret); + cache[cnt].rule_id = 0; + } + } IPACMDBG("On power reset added below rule successfully\n"); iptodot("Private IP", nat_rule.private_ip); @@ -866,7 +1108,7 @@ void NatApp::FlushTempEntries(uint32_t ip_addr, bool isAdd, int NatApp::DelEntriesOnClntDiscon(uint32_t ip_addr) { - int cnt, tmp = 0; + int cnt, tmp = 0, ret; IPACMDBG_H("Received IP address: 0x%x\n", ip_addr); if(ip_addr == INVALID_IP_ADDR) @@ -891,6 +1133,21 @@ int NatApp::DelEntriesOnClntDiscon(uint32_t ip_addr) { if(cache[cnt].enabled == true) { + /* send connections del info to pcie modem first */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0)) + { + ret = DelConnection(cache[cnt].rule_id); + if(ret) + { + IPACMERR("unable to del Connection to pcie modem: %d\n", ret); + } + else + { + /* save the rule id for deletion */ + cache[cnt].rule_id = 0; + } + } + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) { IPACMERR("unable to delete the rule\n"); @@ -913,7 +1170,7 @@ int NatApp::DelEntriesOnClntDiscon(uint32_t ip_addr) int NatApp::DelEntriesOnSTAClntDiscon(uint32_t ip_addr) { - int cnt, tmp = curCnt; + int cnt, tmp = curCnt, ret; IPACMDBG_H("Received IP address: 0x%x\n", ip_addr); if(ip_addr == INVALID_IP_ADDR) @@ -929,6 +1186,21 @@ int NatApp::DelEntriesOnSTAClntDiscon(uint32_t ip_addr) { if(cache[cnt].enabled == true) { + /* send connections del info to pcie modem first */ + if ((CtList->backhaul_mode == Q6_MHI_WAN) && (cache[cnt].dst_nat == true || cache[cnt].protocol == IPPROTO_TCP) && (cache[cnt].rule_id > 0)) + { + ret = DelConnection(cache[cnt].rule_id); + if(ret) + { + IPACMERR("unable to del Connection to pcie modem: %d\n", ret); + } + else + { + /* save the rule id for deletion */ + cache[cnt].rule_id = 0; + } + } + if(ipa_nat_del_ipv4_rule(nat_table_hdl, cache[cnt].rule_hdl) < 0) { IPACMERR("unable to delete the rule\n"); diff --git a/ipacm/src/IPACM_Filtering.cpp b/ipacm/src/IPACM_Filtering.cpp index 3545d81..a158d74 100644 --- a/ipacm/src/IPACM_Filtering.cpp +++ b/ipacm/src/IPACM_Filtering.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -57,6 +57,8 @@ IPACM_Filtering::IPACM_Filtering() { IPACMERR("Failed opening %s.\n", DEVICE_NAME); } + total_num_offload_rules = 0; + pcie_modem_rule_id = 0; } IPACM_Filtering::~IPACM_Filtering() @@ -114,6 +116,242 @@ bool IPACM_Filtering::AddFilteringRule(struct ipa_ioc_add_flt_rule const *ruleTa return true; } +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO +bool IPACM_Filtering::AddFilteringRule_hw_index(struct ipa_ioc_add_flt_rule *ruleTable, int hw_counter_index) +{ + int retval=0, cnt = 0, len = 0; + struct ipa_ioc_add_flt_rule_v2 *ruleTable_v2; + struct ipa_flt_rule_add_v2 flt_rule_entry; + bool ret = true; + + IPACMDBG("Printing filter add attributes\n"); + IPACMDBG("ip type: %d\n", ruleTable->ip); + IPACMDBG("Number of rules: %d\n", ruleTable->num_rules); + IPACMDBG("End point: %d and global value: %d\n", ruleTable->ep, ruleTable->global); + IPACMDBG("commit value: %d\n", ruleTable->commit); + + /* change to v2 format*/ + len = sizeof(struct ipa_ioc_add_flt_rule_v2); + ruleTable_v2 = (struct ipa_ioc_add_flt_rule_v2*)malloc(len); + if (ruleTable_v2 == NULL) + { + IPACMERR("Error Locate ipa_ioc_add_flt_rule_v2 memory...\n"); + return false; + } + memset(ruleTable_v2, 0, len); + ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_flt_rule_add_v2)); + if (!ruleTable_v2->rules) { + IPACMERR("Failed to allocate memory for filtering rules\n"); + ret = false; + goto fail_tbl; + } + + ruleTable_v2->commit = ruleTable->commit; + ruleTable_v2->ep = ruleTable->ep; + ruleTable_v2->global = ruleTable->global; + ruleTable_v2->ip = ruleTable->ip; + ruleTable_v2->num_rules = ruleTable->num_rules; + ruleTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2); + + for (cnt=0; cnt < ruleTable->num_rules; cnt++) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add_v2)); + flt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear; + flt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr; + flt_rule_entry.rule.to_uc = ruleTable->rules[cnt].rule.to_uc; + flt_rule_entry.rule.action = ruleTable->rules[cnt].rule.action; + flt_rule_entry.rule.rt_tbl_hdl = ruleTable->rules[cnt].rule.rt_tbl_hdl; + flt_rule_entry.rule.rt_tbl_idx = ruleTable->rules[cnt].rule.rt_tbl_idx; + flt_rule_entry.rule.eq_attrib_type = ruleTable->rules[cnt].rule.eq_attrib_type; + flt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio; + flt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable; + flt_rule_entry.rule.rule_id = ruleTable->rules[cnt].rule.rule_id; + flt_rule_entry.rule.set_metadata = ruleTable->rules[cnt].rule.set_metadata; + flt_rule_entry.rule.pdn_idx = ruleTable->rules[cnt].rule.pdn_idx; + memcpy(&flt_rule_entry.rule.eq_attrib, + &ruleTable->rules[cnt].rule.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&flt_rule_entry.rule.attrib, + &ruleTable->rules[cnt].rule.attrib, + sizeof(flt_rule_entry.rule.attrib)); + IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt, + ruleTable->rules[cnt].rule.attrib.attrib_mask); + /* 0 means disable hw-counter-sats */ + if (hw_counter_index != 0) + { + flt_rule_entry.rule.enable_stats = 1; + flt_rule_entry.rule.cnt_idx = hw_counter_index; + } + + /* copy to v2 table*/ + memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_flt_rule_add_v2))), + &flt_rule_entry, sizeof(flt_rule_entry)); + } + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_V2, ruleTable_v2); + if (retval != 0) + { + IPACMERR("Failed adding Filtering rule %pK\n", ruleTable_v2); + PERROR("unable to add filter rule:"); + + for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++) + { + if (((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status); + } + } + ret = false; + goto fail_rule; + } + + /* copy results from v2 to v1 format */ + for (int cnt = 0; cnt < ruleTable->num_rules; cnt++) + { + /* copy status to v1 format */ + ruleTable->rules[cnt].status = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status; + ruleTable->rules[cnt].flt_rule_hdl = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].flt_rule_hdl; + + if(((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ((struct ipa_flt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status); + } + } + + IPACMDBG("Added Filtering rule %pK\n", ruleTable_v2); + +fail_rule: + if((void *)ruleTable_v2->rules != NULL) + free((void *)ruleTable_v2->rules); +fail_tbl: + if (ruleTable_v2 != NULL) + free(ruleTable_v2); + return ret; +} + +bool IPACM_Filtering::AddFilteringRuleAfter_hw_index(struct ipa_ioc_add_flt_rule_after *ruleTable, int hw_counter_index) +{ + bool ret = true; +#ifdef FEATURE_IPA_V3 + int retval=0, cnt = 0, len = 0; + struct ipa_ioc_add_flt_rule_after_v2 *ruleTable_v2; + struct ipa_flt_rule_add_v2 flt_rule_entry; + + IPACMDBG("Printing filter add attributes\n"); + IPACMDBG("ep: %d\n", ruleTable->ep); + IPACMDBG("ip type: %d\n", ruleTable->ip); + IPACMDBG("Number of rules: %d\n", ruleTable->num_rules); + IPACMDBG("add_after_hdl: %d\n", ruleTable->add_after_hdl); + IPACMDBG("commit value: %d\n", ruleTable->commit); + + /* change to v2 format*/ + len = sizeof(struct ipa_ioc_add_flt_rule_after_v2); + ruleTable_v2 = (struct ipa_ioc_add_flt_rule_after_v2*)malloc(len); + if (ruleTable_v2 == NULL) + { + IPACMERR("Error Locate ipa_ioc_add_flt_rule_after_v2 memory...\n"); + return false; + } + memset(ruleTable_v2, 0, len); + ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_flt_rule_add_v2)); + if (!ruleTable_v2->rules) { + IPACMERR("Failed to allocate memory for filtering rules\n"); + ret = false; + goto fail_tbl; + } + + ruleTable_v2->commit = ruleTable->commit; + ruleTable_v2->ep = ruleTable->ep; + ruleTable_v2->ip = ruleTable->ip; + ruleTable_v2->num_rules = ruleTable->num_rules; + ruleTable_v2->add_after_hdl = ruleTable->add_after_hdl; + ruleTable_v2->flt_rule_size = sizeof(struct ipa_flt_rule_add_v2); + + for (cnt=0; cnt < ruleTable->num_rules; cnt++) + { + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add_v2)); + flt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear; + flt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr; + flt_rule_entry.rule.to_uc = ruleTable->rules[cnt].rule.to_uc; + flt_rule_entry.rule.action = ruleTable->rules[cnt].rule.action; + flt_rule_entry.rule.rt_tbl_hdl = ruleTable->rules[cnt].rule.rt_tbl_hdl; + flt_rule_entry.rule.rt_tbl_idx = ruleTable->rules[cnt].rule.rt_tbl_idx; + flt_rule_entry.rule.eq_attrib_type = ruleTable->rules[cnt].rule.eq_attrib_type; + flt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio; + flt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable; + flt_rule_entry.rule.rule_id = ruleTable->rules[cnt].rule.rule_id; + flt_rule_entry.rule.set_metadata = ruleTable->rules[cnt].rule.set_metadata; + flt_rule_entry.rule.pdn_idx = ruleTable->rules[cnt].rule.pdn_idx; + memcpy(&flt_rule_entry.rule.eq_attrib, + &ruleTable->rules[cnt].rule.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&flt_rule_entry.rule.attrib, + &ruleTable->rules[cnt].rule.attrib, + sizeof(flt_rule_entry.rule.attrib)); + IPACMDBG("Filter rule:%d attrib mask: 0x%x\n", cnt, + ruleTable->rules[cnt].rule.attrib.attrib_mask); + /* 0 means disable hw-counter-sats */ + if (hw_counter_index != 0) + { + flt_rule_entry.rule.enable_stats = 1; + flt_rule_entry.rule.cnt_idx = hw_counter_index; + } + + /* copy to v2 table*/ + memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_flt_rule_add_v2))), + &flt_rule_entry, sizeof(flt_rule_entry)); + } + + retval = ioctl(fd, IPA_IOC_ADD_FLT_RULE_AFTER_V2, ruleTable_v2); + if (retval != 0) + { + IPACMERR("Failed adding Filtering rule %pK\n", ruleTable_v2); + PERROR("unable to add filter rule:"); + + for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++) + { + if (((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status); + } + } + ret = false; + goto fail_rule; + } + + /* copy results from v2 to v1 format */ + for (int cnt = 0; cnt < ruleTable->num_rules; cnt++) + { + /* copy status to v1 format */ + ruleTable->rules[cnt].status = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status; + ruleTable->rules[cnt].flt_rule_hdl = ((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].flt_rule_hdl; + + if(((struct ipa_flt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0) + { + IPACMERR("Adding Filter rule:%d failed with status:%d\n", + cnt, ((struct ipa_flt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status); + } + } + + IPACMDBG("Added Filtering rule %pK\n", ruleTable_v2); + +fail_rule: + if((void *)ruleTable_v2->rules != NULL) + free((void *)ruleTable_v2->rules); +fail_tbl: + if (ruleTable_v2 != NULL) + free(ruleTable_v2); +#else + if (ruleTable) + IPACMERR("Not support adding Filtering rule %pK\n", ruleTable); +#endif + return ret; +} +#endif //IPA_IOCTL_SET_FNR_COUNTER_INFO + bool IPACM_Filtering::AddFilteringRuleAfter(struct ipa_ioc_add_flt_rule_after const *ruleTable) { #ifdef FEATURE_IPA_V3 @@ -461,6 +699,225 @@ bool IPACM_Filtering::AddWanDLFilteringRule(struct ipa_ioc_add_flt_rule const *r return true; } +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; + 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) + { + IPACMERR("Failed to open %s.\n",WWAN_QMI_IOCTL_DEVICE_NAME); + return false; + } + + if(flt_rule_tbl == NULL) + { + if(mux_id ==0) + { + IPACMERR("Invalid add_offload_req muxd: (%d)\n", mux_id); + close(fd_wwan_ioctl); + return false; + } +#ifdef QMI_IPA_MAX_FILTERS_EX2_V01 + /* used for sending mux_id info to modem for UL sky*/ + IPACMDBG_H("sending mux_id info (%d) to modem for UL\n", mux_id); + memset(&qmi_add_msg, 0, sizeof(qmi_add_msg)); + qmi_add_msg.embedded_call_mux_id_valid = true; + qmi_add_msg.embedded_call_mux_id = mux_id; + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_OFFLOAD_CONNECTION, &qmi_add_msg); + if (ret != 0) + { + IPACMERR("Failed sending WAN_IOC_ADD_OFFLOAD_CONNECTION with ret %d\n ", ret); + close(fd_wwan_ioctl); + return false; + } +#endif + close(fd_wwan_ioctl); + return true; + } + /* check Max offload connections */ + if (total_num_offload_rules + flt_rule_tbl->num_rules > QMI_IPA_MAX_FILTERS_V01) + { + IPACMERR("(%d) add_offload req with curent(%d), exceed max (%d).\n", + flt_rule_tbl->num_rules, total_num_offload_rules, + QMI_IPA_MAX_FILTERS_V01); + close(fd_wwan_ioctl); + return false; + } + else + { + memset(&qmi_add_msg, 0, sizeof(qmi_add_msg)); + + if (flt_rule_tbl->num_rules > 0) + { + qmi_add_msg.filter_spec_ex2_list_valid = true; + } + else + { + IPACMDBG_H("Get %d offload-req\n", flt_rule_tbl->num_rules); + close(fd_wwan_ioctl); + return true; + } + qmi_add_msg.filter_spec_ex2_list_len = flt_rule_tbl->num_rules; + + /* check if we want to take default MHI path */ + if (default_path) + { + qmi_add_msg.default_mhi_path_valid = true; + qmi_add_msg.default_mhi_path = true; + } + + IPACMDBG_H("passing %d offload req to modem. default %d\n", flt_rule_tbl->num_rules, qmi_add_msg.default_mhi_path); + + if(flt_rule_tbl != NULL) + { + for(cnt = flt_rule_tbl->num_rules - 1; cnt >= 0; cnt--) + { + if (pos < QMI_IPA_MAX_FILTERS_V01) + { + if (flt_rule_tbl->ip == IPA_IP_v4) + { + qmi_add_msg.filter_spec_ex2_list[pos].ip_type = QMI_IPA_IP_TYPE_V4_V01; + } else if (flt_rule_tbl->ip == IPA_IP_v6) { + qmi_add_msg.filter_spec_ex2_list[pos].ip_type = QMI_IPA_IP_TYPE_V6_V01; + } else { + IPACMDBG_H("invalid ip-type %d\n", flt_rule_tbl->ip); + close(fd_wwan_ioctl); + return true; + } + + qmi_add_msg.filter_spec_ex2_list[pos].filter_action = GetQmiFilterAction(flt_rule_tbl->rules[cnt].rule.action); + qmi_add_msg.filter_spec_ex2_list[pos].is_mux_id_valid = 1; + qmi_add_msg.filter_spec_ex2_list[pos].mux_id = mux_id; + /* assign the rule-id */ + flt_rule_tbl->rules[cnt].flt_rule_hdl = IPA_PCIE_MODEM_RULE_ID_START + pcie_modem_rule_id; + qmi_add_msg.filter_spec_ex2_list[pos].rule_id = flt_rule_tbl->rules[cnt].flt_rule_hdl; + qmi_add_msg.filter_spec_ex2_list[pos].is_rule_hashable = flt_rule_tbl->rules[cnt].rule.hashable; + memcpy(&qmi_add_msg.filter_spec_ex2_list[pos].filter_rule, + &flt_rule_tbl->rules[cnt].rule.eq_attrib, + 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; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); + } + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_ADD_OFFLOAD_CONNECTION, &qmi_add_msg); + if (ret != 0) + { + IPACMERR("Failed sending WAN_IOC_ADD_OFFLOAD_CONNECTION with ret %d\n ", ret); + close(fd_wwan_ioctl); + return false; + } + } + /* update total_num_offload_rules */ + total_num_offload_rules += flt_rule_tbl->num_rules; + IPACMDBG_H("total_num_offload_rules %d \n", total_num_offload_rules); + close(fd_wwan_ioctl); + return true; +#else + if(flt_rule_tbl != NULL) + { + IPACMERR("Not support (%d) AddOffloadFilteringRule with mux-id (%d) and default path = %d\n", flt_rule_tbl->num_rules, mux_id, default_path); + } + return false; +#endif +} + +bool IPACM_Filtering::DelOffloadFilteringRule(struct ipa_ioc_del_flt_rule const *flt_rule_tbl) +{ +#ifdef WAN_IOCTL_ADD_OFFLOAD_CONNECTION + bool result = true; + int ret = 0, cnt, pos = 0; + ipa_remove_offload_connection_req_msg_v01 qmi_del_msg; + int 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; + } + + if(flt_rule_tbl == NULL) + { + IPACMERR("Invalid add_offload_req\n"); + result = false; + goto fail; + } + + /* check # of offload connections */ + if (flt_rule_tbl->num_hdls > total_num_offload_rules) { + IPACMERR("(%d) del_offload req , exceed curent(%d)\n", + flt_rule_tbl->num_hdls, total_num_offload_rules); + result = false; + goto fail; + } + else + { + memset(&qmi_del_msg, 0, sizeof(qmi_del_msg)); + + if (flt_rule_tbl->num_hdls > 0) + { + qmi_del_msg.filter_handle_list_valid = true; + } + else + { + IPACMERR("Get %d offload-req\n", flt_rule_tbl->num_hdls); + goto fail; + } + qmi_del_msg.filter_handle_list_len = flt_rule_tbl->num_hdls; + + IPACMDBG_H("passing %d offload req to modem.\n", flt_rule_tbl->num_hdls); + + if(flt_rule_tbl != NULL) + { + for(cnt = flt_rule_tbl->num_hdls - 1; cnt >= 0; cnt--) + { + if (pos < QMI_IPA_MAX_FILTERS_V01) + { + /* passing rule-id to wan-driver */ + qmi_del_msg.filter_handle_list[pos].filter_spec_identifier = flt_rule_tbl->hdl[cnt].hdl; + pos++; + } + else + { + IPACMERR(" QMI only support max %d rules, current (%d)\n ",QMI_IPA_MAX_FILTERS_V01, pos); + result = false; + goto fail; + } + } + } + + ret = ioctl(fd_wwan_ioctl, WAN_IOC_RMV_OFFLOAD_CONNECTION, &qmi_del_msg); + if (ret != 0) + { + IPACMERR("Failed deleting Filtering rule %pK with ret %d\n ", &qmi_del_msg, ret); + result = false; + goto fail; + } + } + /* update total_num_offload_rules */ + total_num_offload_rules -= flt_rule_tbl->num_hdls; + IPACMDBG_H("total_num_offload_rules %d \n", total_num_offload_rules); + +fail: + close(fd_wwan_ioctl); + return result; +#else + if(flt_rule_tbl != NULL) + { + IPACMERR("Not support (%d) DelOffloadFilteringRule\n", flt_rule_tbl->num_hdls); + } + return false; +#endif +} + bool IPACM_Filtering::SendFilteringRuleIndex(struct ipa_fltr_installed_notif_req_msg_v01* table) { int ret = 0; diff --git a/ipacm/src/IPACM_Iface.cpp b/ipacm/src/IPACM_Iface.cpp index 512846f..ec4a9ea 100644 --- a/ipacm/src/IPACM_Iface.cpp +++ b/ipacm/src/IPACM_Iface.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013-2018, The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -88,12 +88,14 @@ IPACM_Iface::IPACM_Iface(int iface_index) } /* software routing enable */ -int IPACM_Iface::handle_software_routing_enable(void) +int IPACM_Iface::handle_software_routing_enable(bool mhip) { - + int fd =0; int res = IPACM_SUCCESS; struct ipa_flt_rule_add flt_rule_entry; ipa_ioc_add_flt_rule *m_pFilteringTable; + /* contruct filter rules to pcie modem */ + ipa_ioc_generate_flt_eq flt_eq; IPACMDBG("\n"); if (softwarerouting_act == true) @@ -121,11 +123,9 @@ int IPACM_Iface::handle_software_routing_enable(void) } m_pFilteringTable->commit = 1; - m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; m_pFilteringTable->global = false; m_pFilteringTable->num_rules = (uint8_t)1; - /* Configuring Software-Routing Filtering Rule */ memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); @@ -143,10 +143,48 @@ int IPACM_Iface::handle_software_routing_enable(void) memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); /* check iface is v4 or v6 or both*/ -// if (ip_type == IPA_IP_MAX) -// { + /* handle v4 */ m_pFilteringTable->ip = IPA_IP_v4; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + + if (mhip) + { + /* generate eq */ + 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_v4; + + + if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct + { + 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)); + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add rule */ + if(false == m_filtering.AddOffloadFilteringRule(m_pFilteringTable, IPACM_Iface::ipacmcfg->GetQmapId(), 1)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + } + else + { + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) { IPACMERR("Error Adding Filtering rule, aborting...\n"); @@ -159,46 +197,44 @@ int IPACM_Iface::handle_software_routing_enable(void) res = IPACM_FAILURE; goto fail; } - IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); - IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); + } + + IPACMDBG("soft-routing ipv4 flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); /* copy filter hdls */ software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; - /* handle v6*/ m_pFilteringTable->ip = IPA_IP_v6; - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + if (mhip) + { + /* generate eq */ + 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(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct { - IPACMERR("Error Adding Filtering rule, aborting...\n"); + IPACMERR("Failed to get eq_attrib\n"); res = IPACM_FAILURE; goto fail; } - else if (m_pFilteringTable->rules[0].status) + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add rule */ + if(false == m_filtering.AddOffloadFilteringRule(m_pFilteringTable, IPACM_Iface::ipacmcfg->GetQmapId(), 1)) { - IPACMDBG("adding flt rule failed status=0x%x\n", m_pFilteringTable->rules[0].status); + IPACMERR("Failed to install WAN DL filtering table.\n"); res = IPACM_FAILURE; goto fail; } - - IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); - IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); - /* copy filter hdls */ - software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; - softwarerouting_act = true; -#if 0 } else { - if (ip_type == IPA_IP_v4) - { - m_pFilteringTable->ip = IPA_IP_v4; - } - else - { - m_pFilteringTable->ip = IPA_IP_v6; - } - + m_pFilteringTable->ep = rx_prop->rx[0].src_pipe; if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) { IPACMERR("Error Adding Filtering rule, aborting...\n"); @@ -211,32 +247,29 @@ int IPACM_Iface::handle_software_routing_enable(void) res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + } - IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, ip_type, 1); - IPACMDBG("soft-routing flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); + IPACMDBG("soft-routing ipv6 flt rule hdl0=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl); /* copy filter hdls */ - if (ip_type == IPA_IP_v4) - { - software_routing_fl_rule_hdl[0] = m_pFilteringTable->rules[0].flt_rule_hdl; - } - else - { software_routing_fl_rule_hdl[1] = m_pFilteringTable->rules[0].flt_rule_hdl; - } softwarerouting_act = true; - } -#endif fail: + close(fd); + if(m_pFilteringTable != NULL) + { free(m_pFilteringTable); - + } return res; } /* software routing disable */ -int IPACM_Iface::handle_software_routing_disable(void) +int IPACM_Iface::handle_software_routing_disable(bool mhip) { - int res = IPACM_SUCCESS; + int len, res = IPACM_SUCCESS; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + struct ipa_flt_rule_del flt_rule_entry; if (rx_prop == NULL) { @@ -250,63 +283,96 @@ int IPACM_Iface::handle_software_routing_disable(void) return IPACM_SUCCESS; } -// if (ip_type == IPA_IP_MAX) -// { - /* ipv4 case */ - if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0], - IPA_IP_v4, 1) == false) + if(mhip) + { + len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) { - IPACMERR("Error Adding Filtering rule, aborting...\n"); + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_hdls = (uint8_t)1; + + if (software_routing_fl_rule_hdl[0] == 0) + { + IPACMERR("invalid ipv4_exception_hdl.\n"); res = IPACM_FAILURE; goto fail; } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); - /* ipv6 case */ - if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1], - IPA_IP_v6, 1) == false) + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = software_routing_fl_rule_hdl[0]; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) { - IPACMERR("Error Adding Filtering rule, aborting...\n"); + IPACMERR("Failed to delete MHI ipv4 exception rule.\n"); res = IPACM_FAILURE; goto fail; } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); - softwarerouting_act = false; -#if 0 + software_routing_fl_rule_hdl[0] = 0; } else { - if (ip_type == IPA_IP_v4) + /* ipv4 case */ + if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[0], + IPA_IP_v4, 1) == false) { - ip = IPA_IP_v4; + IPACMERR("Error Adding Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; } - else + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, 1); + + if(mhip) + { + pFilteringTable->ip = IPA_IP_v6; + if (software_routing_fl_rule_hdl[1] == 0) { - ip = IPA_IP_v6; + IPACMERR("invalid ipv6_exception_hdl.\n"); + res = IPACM_FAILURE; + goto fail; } + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = software_routing_fl_rule_hdl[1]; - if (ip_type == IPA_IP_v4) + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) { - flt_hdl = software_routing_fl_rule_hdl[0]; + IPACMERR("Failed to delete MHI ipv6 exception rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + software_routing_fl_rule_hdl[1] = 0; } else { - flt_hdl = software_routing_fl_rule_hdl[1]; - } - - if (m_filtering.DeleteFilteringHdls(&flt_hdl, ip, 1) == false) + /* ipv6 case */ + if (m_filtering.DeleteFilteringHdls(&software_routing_fl_rule_hdl[1], + IPA_IP_v6, 1) == false) { IPACMERR("Error Adding Filtering rule, aborting...\n"); res = IPACM_FAILURE; goto fail; } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, ip, 1); - softwarerouting_act = false; } -#endif + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + softwarerouting_act = false; fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } return res; } @@ -633,6 +699,7 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) int res = IPACM_SUCCESS, len = 0; struct ipa_flt_rule_add flt_rule_entry; ipa_ioc_add_flt_rule *m_pFilteringTable; + bool result; /* Adding this hack because WLAN may not registered for Rx-endpoint, other ifaces will always have*/ const char *dev_wlan0="wlan0"; @@ -739,7 +806,25 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) #endif memcpy(&(m_pFilteringTable->rules[2]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + if(ipa_if_cate == WAN_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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_ALL); + } else 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(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else + { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (result == false) { IPACMERR("Error Adding Filtering rule, aborting...\n"); res = IPACM_FAILURE; @@ -921,7 +1006,20 @@ int IPACM_Iface::init_fl_rule(ipa_ip_type iptype) memcpy(&(m_pFilteringTable->rules[7]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); #endif - if (m_filtering.AddFilteringRule(m_pFilteringTable) == false) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + if(ipa_if_cate == WAN_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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (result == false) { IPACMERR("Error Adding Filtering rule, aborting...\n"); res = IPACM_FAILURE; @@ -1045,6 +1143,58 @@ void IPACM_Iface::config_ip_type(ipa_ip_type iptype) return; } +void IPACM_Iface::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib) +{ + if(attrib == NULL) + { + IPACMERR("Attribute pointer is NULL.\n"); + return; + } + + if(iptype == IPA_IP_v6) + { + int i; + for(i=0; i<4; i++) + { + attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]); + attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]); + attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]); + attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]); + } + } + else + { + IPACMDBG_H("IP type is not IPv6, do nothing: %d\n", iptype); + } + + return; +} + +bool IPACM_Iface::is_global_ipv6_addr(uint32_t* ipv6_addr) +{ + uint32_t ipv6_link_local_prefix, ipv6_link_local_prefix_mask; + ipv6_link_local_prefix = 0xFE800000; + ipv6_link_local_prefix_mask = 0xFFC00000; + + if(ipv6_addr == NULL) + { + IPACMERR("IPv6 address is empty.\n"); + return false; + } + IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]); + + if((ipv6_addr[0] & ipv6_link_local_prefix_mask) == (ipv6_link_local_prefix & ipv6_link_local_prefix_mask)) + { + IPACMDBG_H("This IPv6 address is link local.\n"); + return false; + } + else + { + IPACMDBG_H("This IPv6 address is not link local.\n"); + return true; + } +} + void IPACM_Iface::delete_iface(void) { IPACMDBG_H("netdev (%s):ipa_index (%d) instance close \n", diff --git a/ipacm/src/IPACM_IfaceManager.cpp b/ipacm/src/IPACM_IfaceManager.cpp index 1c7dfc4..3e825dd 100644 --- a/ipacm/src/IPACM_IfaceManager.cpp +++ b/ipacm/src/IPACM_IfaceManager.cpp @@ -484,6 +484,7 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param) } else { + IPACM_EvtDispatcher::registr(IPA_COALESCE_NOTICE, w); IPACM_EvtDispatcher::registr(IPA_LINK_DOWN_EVENT, w); } diff --git a/ipacm/src/IPACM_Lan.cpp b/ipacm/src/IPACM_Lan.cpp index 827839b..755d730 100644 --- a/ipacm/src/IPACM_Lan.cpp +++ b/ipacm/src/IPACM_Lan.cpp @@ -184,9 +184,9 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) handle_tethering_client(false, IPACM_CLIENT_MAX); #else handle_tethering_client(false, IPACM_CLIENT_USB); -#endif +#endif // FEATURE_IPACM_HAL end } -#endif +#endif // FEATURE_IPA_ANDROID end memset(is_downstream_set, 0, sizeof(is_downstream_set)); memset(is_upstream_set, 0, sizeof(is_upstream_set)); @@ -195,9 +195,9 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) #ifdef FEATURE_IPACM_HAL /* check if Upstream was set before as WIFI with RNDIS case */ - if(ipa_if_cate == LAN_IF && IPACM_Wan::backhaul_is_sta_mode == true) /* LTE */ + if(ipa_if_cate == LAN_IF && IPACM_Wan::backhaul_mode == WLAN_WAN) /* LTE */ { - IPACMDBG_H(" Skip the Upstream falg set on LAN instance (%d) with WIFI backhaul (%d)\n", ipa_if_cate, IPACM_Wan::backhaul_is_sta_mode ); /* RNDIS+WIFI not support on msm*/ + IPACMDBG_H(" Skip the Upstream flag set on LAN instance (%d) with WIFI backhaul (%d)\n", ipa_if_cate, IPACM_Wan::backhaul_mode ); /* RNDIS+WIFI not support on msm*/ return; } @@ -213,7 +213,7 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index) IPACMDBG_H("Upstream was set previously for ipv6, change is_upstream_set flag\n"); is_upstream_set[IPA_IP_v6] = true; } -#endif +#endif // FEATURE_IPACM_HAL end return; } @@ -399,7 +399,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) handle_private_subnet_android(data->iptype); #else handle_private_subnet(data->iptype); -#endif +#endif // FEATURE_IPA_ANDROID end } else { @@ -419,14 +419,14 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) handle_private_subnet_android(data->iptype); #else handle_private_subnet(data->iptype); -#endif +#endif // FEATURE_IPA_ANDROID end #ifndef FEATURE_IPACM_HAL if (IPACM_Wan::isWanUP(ipa_if_num)) { if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) { - if(IPACM_Wan::backhaul_is_sta_mode == false) + if(IPACM_Wan::backhaul_mode == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); handle_wan_up_ex(ext_prop, IPA_IP_v4, @@ -448,7 +448,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) { memcpy(ipv6_prefix, IPACM_Wan::backhaul_ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); - if(IPACM_Wan::backhaul_is_sta_mode == false) + if(IPACM_Wan::backhaul_mode == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -474,7 +474,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Upstream was set previously for ipv6, change is_upstream_set flag\n"); is_upstream_set[IPA_IP_v6] = true; } -#endif +#endif //FEATURE_IPACM_HAL end /* Post event to NAT */ if (data->iptype == IPA_IP_v4) { @@ -511,7 +511,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) { /* handle software routing enable event*/ IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); - handle_software_routing_enable(); + handle_software_routing_enable(false); } } @@ -528,7 +528,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s xlat_mux_id: %d\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s, xlat %d\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name, data_wan_tether->xlat_mux_id); @@ -539,7 +539,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) return; } #else /* not offload rndis on WIFI mode on MSM targets */ - if (data_wan_tether->is_sta) + if (data_wan_tether->backhaul_type == WLAN_WAN) { IPACMERR("Not support RNDIS offload on WIFI mode, dun install UL filter rules for WIFI mode\n"); @@ -577,7 +577,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) } /* end of for loop */ return; } -#endif +#endif // FEATURE_IPACM_HAL end if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { #ifdef FEATURE_IPACM_HAL @@ -588,7 +588,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) if (is_downstream_set[IPA_IP_v4] == true) { IPACMDBG_H("Downstream was set before, adding UL rules.\n"); - if (data_wan_tether->is_sta == false) + if (data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); handle_wan_up_ex(ext_prop, IPA_IP_v4, @@ -599,14 +599,14 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) } } #else - if (data_wan_tether->is_sta == false) + if (data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan_tether->xlat_mux_id); } else { handle_wan_up(IPA_IP_v4); } -#endif +#endif // FEATURE_IPACM_HAL end } break; @@ -619,7 +619,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); #ifndef FEATURE_IPACM_HAL @@ -628,7 +628,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("IPA_HANDLE_WAN_UP_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); return; } -#endif +#endif // FEATURE_IPACM_HAL end if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { #ifdef FEATURE_IPACM_HAL @@ -642,7 +642,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Downstream was set before, adding UL rules.\n"); memcpy(ipv6_prefix, data_wan_tether->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix); - if (data_wan_tether->is_sta == false) + if (data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -654,14 +654,14 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) } } #else - if (data_wan_tether->is_sta == false) + if (data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); } else { handle_wan_up(IPA_IP_v6); } -#endif +#endif // FEATURE_IPACM_HAL end } break; @@ -673,7 +673,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); #ifndef FEATURE_IPACM_HAL @@ -682,7 +682,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("IPA_HANDLE_WAN_DOWN_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); return; } -#endif +#endif // FEATURE_IPACM_HAL end if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { #ifdef FEATURE_IPACM_HAL @@ -693,12 +693,12 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) if(is_downstream_set[IPA_IP_v4] == true) { IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); - handle_wan_down(data_wan_tether->is_sta); + handle_wan_down(data_wan_tether->backhaul_type); } } #else - handle_wan_down(data_wan_tether->is_sta); -#endif + handle_wan_down(data_wan_tether->backhaul_type); +#endif // FEATURE_IPACM_HAL end } break; @@ -710,7 +710,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); #ifndef FEATURE_IPACM_HAL @@ -719,7 +719,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("IPA_HANDLE_WAN_DOWN_V6_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num); return; } -#endif +#endif // FEATURE_IPACM_HAL end if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { #ifdef FEATURE_IPACM_HAL @@ -732,14 +732,14 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); /* reset usb-client ipv6 rt-rules */ handle_lan_client_reset_rt(IPA_IP_v6); - handle_wan_down_v6(data_wan_tether->is_sta); + handle_wan_down_v6(data_wan_tether->backhaul_type); } } #else /* reset usb-client ipv6 rt-rules */ handle_lan_client_reset_rt(IPA_IP_v6); - handle_wan_down_v6(data_wan_tether->is_sta); -#endif + handle_wan_down_v6(data_wan_tether->backhaul_type); +#endif // FEATURE_IPACM_HAL end } break; @@ -750,6 +750,25 @@ 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); @@ -771,7 +790,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) install_ipv6_prefix_flt_rule(ipv6_prefix); } - if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + if (IPACM_Wan::backhaul_mode == Q6_WAN) /* LTE */ { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype); if (data->prefix.iptype == IPA_IP_v4) @@ -812,10 +831,10 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Upstream was set before, deleting UL rules.\n"); if (data->prefix.iptype == IPA_IP_v4) { - handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + handle_wan_down(IPACM_Wan::backhaul_mode); /* LTE STA */ } else { handle_lan_client_reset_rt(IPA_IP_v6); - handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + handle_wan_down_v6(IPACM_Wan::backhaul_mode); /* LTE STA */ } } } @@ -823,7 +842,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) break; } -#else +#else // above Andorid case IPA_HANDLE_WAN_UP: IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n"); @@ -833,10 +852,10 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - if (data_wan->is_sta == false) + if (data_wan->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); @@ -857,12 +876,12 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); - if (data_wan->is_sta == false) + if (data_wan->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -882,10 +901,10 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - handle_wan_down(data_wan->is_sta); + handle_wan_down(data_wan->backhaul_type); } break; @@ -902,13 +921,13 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) /* reset usb-client ipv6 rt-rules */ handle_lan_client_reset_rt(IPA_IP_v6); - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { - handle_wan_down_v6(data_wan->is_sta); + handle_wan_down_v6(data_wan->backhaul_type); } break; -#endif +#endif // FEATURE_IPA_ANDROID end case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT: { @@ -919,9 +938,9 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) /* if RNDIS under WIFI mode in MSM, dun add RT rule*/ #ifdef FEATURE_IPACM_HAL - if(IPACM_Wan::backhaul_is_sta_mode == true) /* WIFI */ + if(IPACM_Wan::backhaul_mode == WLAN_WAN) /* WIFI */ { - IPACMDBG_H(" dun construct header and RT-rules for RNDIS-PC in WIFI mode on MSM targets (STA %d) \n", IPACM_Wan::backhaul_is_sta_mode); + IPACMDBG_H(" dun construct header and RT-rules for RNDIS-PC in WIFI mode on MSM targets (STA %d) \n", IPACM_Wan::backhaul_mode); return; } #endif @@ -1051,13 +1070,13 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) case IPA_SW_ROUTING_ENABLE: IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); /* handle software routing enable event*/ - handle_software_routing_enable(); + handle_software_routing_enable(false); break; case IPA_SW_ROUTING_DISABLE: IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); /* handle software routing disable event*/ - handle_software_routing_disable(); + handle_software_routing_disable(false); break; case IPA_CRADLE_WAN_MODE_SWITCH: @@ -1086,7 +1105,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_EVENT event.\n"); if (IPACM_Wan::isWanUP(ipa_if_num) || IPACM_Wan::isWanUP_V6(ipa_if_num)) { - if(IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + if(IPACM_Wan::backhaul_mode == Q6_WAN) /* LTE */ { ipa_get_data_stats_resp_msg_v01 *data = (ipa_get_data_stats_resp_msg_v01 *)param; IPACMDBG("Received IPA_TETHERING_STATS_UPDATE_STATS ipa_stats_type: %d\n",data->ipa_stats_type); @@ -1193,7 +1212,7 @@ int IPACM_Lan::handle_del_ipv6_addr(ipacm_event_data_all *data) } /* delete filter rule for wan_down event for IPv4*/ -int IPACM_Lan::handle_wan_down(bool is_sta_mode) +int IPACM_Lan::handle_wan_down(ipacm_wan_iface_type backhaul_mode) { ipa_fltr_installed_notif_req_msg_v01 flt_index; int fd; @@ -1205,7 +1224,15 @@ int IPACM_Lan::handle_wan_down(bool is_sta_mode) return IPACM_FAILURE; } - if(is_sta_mode == false && modem_ul_v4_set == true) +#ifdef FEATURE_IPA_ANDROID + /* indicate v4-offload remove */ + if (IPACM_Wan::isXlat() && (IPACM_OffloadManager::num_offload_v4_tethered_iface > 0)) { + IPACM_OffloadManager::num_offload_v4_tethered_iface--; + IPACMDBG_H("num_offload_v4_tethered_iface %d\n", IPACM_OffloadManager::num_offload_v4_tethered_iface); + } +#endif + + if(backhaul_mode == Q6_WAN && modem_ul_v4_set == true) { if (num_wan_ul_fl_rule_v4 > MAX_WAN_UL_FILTER_RULES) { @@ -1499,6 +1526,7 @@ int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) { struct ipa_flt_rule_add flt_rule_entry; int i; + bool result; ipa_ioc_add_flt_rule *m_pFilteringTable; @@ -1562,7 +1590,20 @@ int IPACM_Lan::handle_private_subnet(ipa_ip_type iptype) IPACMDBG_H("Loop %d 5\n", i); } - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#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(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (result == false) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -1591,6 +1632,7 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) struct ipa_flt_rule_add flt_rule_entry; int len = 0; ipa_ioc_add_flt_rule *m_pFilteringTable; + bool result; IPACMDBG_H("set WAN interface as default filter rule\n"); @@ -1665,7 +1707,20 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) flt_rule_entry.rule.attrib.u.v4.src_addr = prefix[IPA_IP_v4].v4Addr; #endif memcpy(&m_pFilteringTable->rules[0], &flt_rule_entry, sizeof(flt_rule_entry)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + +#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(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + if (result == false) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -1743,18 +1798,32 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type) /* only offload UL traffic of certain clients */ #ifdef FEATURE_IPACM_HAL flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_SRC_ADDR; - flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = ntohl(prefix[IPA_IP_v6].v6Mask[0]); - flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = ntohl(prefix[IPA_IP_v6].v6Mask[1]); - flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = ntohl(prefix[IPA_IP_v6].v6Mask[2]); - flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = ntohl(prefix[IPA_IP_v6].v6Mask[3]); - flt_rule_entry.rule.attrib.u.v6.src_addr[0] = ntohl(prefix[IPA_IP_v6].v6Addr[0]); - flt_rule_entry.rule.attrib.u.v6.src_addr[1] = ntohl(prefix[IPA_IP_v6].v6Addr[1]); - flt_rule_entry.rule.attrib.u.v6.src_addr[2] = ntohl(prefix[IPA_IP_v6].v6Addr[2]); - flt_rule_entry.rule.attrib.u.v6.src_addr[3] = ntohl(prefix[IPA_IP_v6].v6Addr[3]); + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[0] = prefix[IPA_IP_v6].v6Mask[0]; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[1] = prefix[IPA_IP_v6].v6Mask[1]; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[2] = prefix[IPA_IP_v6].v6Mask[2]; + flt_rule_entry.rule.attrib.u.v6.src_addr_mask[3] = prefix[IPA_IP_v6].v6Mask[3]; + flt_rule_entry.rule.attrib.u.v6.src_addr[0] = prefix[IPA_IP_v6].v6Addr[0]; + flt_rule_entry.rule.attrib.u.v6.src_addr[1] = prefix[IPA_IP_v6].v6Addr[1]; + flt_rule_entry.rule.attrib.u.v6.src_addr[2] = prefix[IPA_IP_v6].v6Addr[2]; + flt_rule_entry.rule.attrib.u.v6.src_addr[3] = prefix[IPA_IP_v6].v6Addr[3]; #endif memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + +#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(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (result == false) { IPACMERR("Error Adding Filtering rule, aborting...\n"); free(m_pFilteringTable); @@ -1817,6 +1886,7 @@ 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) { + IPACMDBG_H("check getXlat_Mux_Id:%d\n", IPACM_Wan::getXlat_Mux_Id()); IPACMDBG_H("IPA_IP_v4 xlat_mux_id: %d, modem_ul_v4_set %d\n", xlat_mux_id, modem_ul_v4_set); ret = handle_uplink_filter_rule(ext_prop, iptype, xlat_mux_id); modem_ul_v4_set = true; @@ -2401,6 +2471,15 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num] = rt_rule->rules[0].rt_rule_hdl; IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, get_client_memptr(eth_client, eth_index)->eth_rt_hdl[tx_index].eth_rt_rule_hdl_v6_wan[v6_num], iptype); + + /* send client-v6 info to pcie modem only with global ipv6 with tx_index = 1 one time*/ + if(is_global_ipv6_addr(get_client_memptr(eth_client, eth_index)->v6_addr[v6_num]) && (IPACM_Wan::backhaul_mode == Q6_MHI_WAN)) + { + if (add_connection(eth_index, v6_num)) + { + IPACMERR("PCIE filter rule addition failed! (%d-client) %d v6-entry\n",eth_index, v6_num); + } + } } } @@ -2928,8 +3007,8 @@ int IPACM_Lan::handle_down_evt() /* delete wan filter rule */ if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL) { - IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); - handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_mode); + handle_wan_down(IPACM_Wan::backhaul_mode); #ifdef FEATURE_IPA_ANDROID #ifndef FEATURE_IPACM_HAL /* Clean-up tethered-iface list */ @@ -2940,8 +3019,8 @@ int IPACM_Lan::handle_down_evt() if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL) { - IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); - handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_mode); + handle_wan_down_v6(IPACM_Wan::backhaul_mode); #ifdef FEATURE_IPA_ANDROID /* Clean-up tethered-iface list */ IPACM_Wan::delete_tether_iface(IPA_IP_v6, ipa_if_num); @@ -3149,7 +3228,7 @@ fail: /* check software routing fl rule hdl */ if (softwarerouting_act == true && rx_prop != NULL) { - handle_software_routing_disable(); + handle_software_routing_disable(false); } if (odu_route_rule_v4_hdl != NULL) @@ -3205,7 +3284,8 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptyp int fd; int i, index, eq_index; uint32_t value = 0; - uint8_t qmap_id; + uint8_t qmap_id, xlat_debug; + bool result; IPACMDBG_H("Set modem UL flt rules\n"); @@ -3263,13 +3343,14 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptyp flt_index.retain_header = 0; flt_index.embedded_call_mux_id_valid = 1; qmap_id = IPACM_Iface::ipacmcfg->GetQmapId(); + xlat_debug = IPACM_Wan::getXlat_Mux_Id(); flt_index.embedded_call_mux_id = qmap_id; #ifndef FEATURE_IPA_V3 - IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", - flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d, xlat_mux id: %d, wan-debug %d\n", + flt_index.source_pipe_index, flt_index.filter_index_list_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id, xlat_mux_id, xlat_debug); #else /* defined (FEATURE_IPA_V3) */ - IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d\n", - flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id); + IPACMDBG_H("flt_index: src pipe: %d, num of rules: %d, ebd pipe: %d, mux id: %d, xlat_mux id: %d, wan-debug %d\n", + flt_index.source_pipe_index, flt_index.rule_id_len, flt_index.embedded_pipe_index, flt_index.embedded_call_mux_id, xlat_mux_id, xlat_debug); #endif len = sizeof(struct ipa_ioc_add_flt_rule) + prop->num_ext_props * sizeof(struct ipa_flt_rule_add); pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); @@ -3340,6 +3421,13 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptyp } /* Handle XLAT configuration */ + /* temp wa to reset xlat_mux_id to qmap_id if it's xlat call */ + if (IPACM_Wan::isXlat() && (iptype == IPA_IP_v4)) + { + IPACMDBG_H("WA to replace xlat_mux_id %d with qmap_id: %d\n", xlat_mux_id, qmap_id); + xlat_mux_id = qmap_id; + } + if ((iptype == IPA_IP_v4) && prop->prop[cnt].is_xlat_rule && (xlat_mux_id != 0)) { /* fill the value of meta-data */ @@ -3490,7 +3578,20 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptyp goto fail; } - if(false == m_filtering.AddFilteringRule(pFilteringTable)) +#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(pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRule(pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(pFilteringTable); +#endif + + if(result == false) { IPACMERR("Error Adding RuleTable to Filtering, aborting...\n"); ret = IPACM_FAILURE; @@ -3532,7 +3633,7 @@ fail: return ret; } -int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) +int IPACM_Lan::handle_wan_down_v6(ipacm_wan_iface_type backhaul_mode) { ipa_fltr_installed_notif_req_msg_v01 flt_index; int fd; @@ -3548,7 +3649,7 @@ int IPACM_Lan::handle_wan_down_v6(bool is_sta_mode) memset(ipv6_prefix, 0, sizeof(ipv6_prefix)); - if(is_sta_mode == false && modem_ul_v6_set == true) + if(backhaul_mode == Q6_WAN && modem_ul_v6_set == true) { if (num_wan_ul_fl_rule_v6 > MAX_WAN_UL_FILTER_RULES) { @@ -3786,6 +3887,7 @@ int IPACM_Lan::install_ipv4_icmp_flt_rule() int len; struct ipa_ioc_add_flt_rule* flt_rule; struct ipa_flt_rule_add flt_rule_entry; + bool result; if(rx_prop != NULL) { @@ -3822,7 +3924,20 @@ int IPACM_Lan::install_ipv4_icmp_flt_rule() flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP; memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (m_filtering.AddFilteringRule(flt_rule) == false) +#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) { IPACMERR("Error Adding Filtering rule, aborting...\n"); free(flt_rule); @@ -3845,6 +3960,7 @@ int IPACM_Lan::install_ipv6_icmp_flt_rule() int len; struct ipa_ioc_add_flt_rule* flt_rule; struct ipa_flt_rule_add flt_rule_entry; + bool result; if(rx_prop != NULL) { @@ -3880,7 +3996,20 @@ int IPACM_Lan::install_ipv6_icmp_flt_rule() flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (m_filtering.AddFilteringRule(flt_rule) == false) +#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) { IPACMERR("Error Adding Filtering rule, aborting...\n"); free(flt_rule); @@ -3913,6 +4042,7 @@ int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) int i, len, res = IPACM_SUCCESS; struct ipa_flt_rule_add flt_rule; ipa_ioc_add_flt_rule* pFilteringTable; + bool result; len = sizeof(struct ipa_ioc_add_flt_rule) + IPA_MAX_PRIVATE_SUBNET_ENTRIES * sizeof(struct ipa_flt_rule_add); @@ -3956,7 +4086,20 @@ int IPACM_Lan::add_dummy_private_subnet_flt_rule(ipa_ip_type iptype) memcpy(&(pFilteringTable->rules[i]), &flt_rule, sizeof(struct ipa_flt_rule_add)); } - if (false == m_filtering.AddFilteringRule(pFilteringTable)) +#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(pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRule(pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(pFilteringTable); +#endif + + if (result == false) { IPACMERR("Error adding dummy private subnet v4 flt rule\n"); res = IPACM_FAILURE; @@ -4081,6 +4224,7 @@ 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; if(rx_prop != NULL) { @@ -4123,7 +4267,20 @@ int IPACM_Lan::install_ipv6_prefix_flt_rule(uint32_t* prefix) 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_add)); - if (m_filtering.AddFilteringRule(flt_rule) == false) +#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) { IPACMERR("Error Adding Filtering rule, aborting...\n"); free(flt_rule); @@ -4575,7 +4732,7 @@ int IPACM_Lan::set_tether_client(wan_ioctl_set_tether_client_pipe *tether_client } } - ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, &tether_client); + ret = ioctl(fd_wwan_ioctl, WAN_IOC_SET_TETHER_CLIENT_PIPE, tether_client); if(ret != 0) { IPACMERR("Failed set tether-client-pipe %p with ret %d\n ", &tether_client, ret); @@ -4966,6 +5123,7 @@ int IPACM_Lan::eth_bridge_add_flt_rule(uint8_t *mac, uint32_t rt_tbl_hdl, ipa_ip int len; struct ipa_flt_rule_add flt_rule_entry; struct ipa_ioc_add_flt_rule_after *pFilteringTable = NULL; + bool result; if (rx_prop == NULL || tx_prop == NULL) { @@ -5014,7 +5172,19 @@ int IPACM_Lan::eth_bridge_add_flt_rule(uint8_t *mac, uint32_t rt_tbl_hdl, ipa_ip memset(flt_rule_entry.rule.attrib.dst_mac_addr_mask, 0xFF, sizeof(flt_rule_entry.rule.attrib.dst_mac_addr_mask)); memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); - if (false == m_filtering.AddFilteringRuleAfter(pFilteringTable)) +#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.AddFilteringRuleAfter_hw_index(pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRuleAfter(pFilteringTable); + } +#else + result = m_filtering.AddFilteringRuleAfter(pFilteringTable); +#endif + if (result == false) { IPACMERR("Failed to add client filtering rules.\n"); res = IPACM_FAILURE; @@ -5892,6 +6062,7 @@ int IPACM_Lan::add_tcp_syn_flt_rule(ipa_ip_type iptype) int len; struct ipa_flt_rule_add flt_rule_entry; ipa_ioc_add_flt_rule *m_pFilteringTable; + bool result; if(rx_prop == NULL) { @@ -5936,8 +6107,20 @@ int IPACM_Lan::add_tcp_syn_flt_rule(ipa_ip_type iptype) } memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); +#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(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif - if(false == m_filtering.AddFilteringRule(m_pFilteringTable)) + if(result == false) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -5997,7 +6180,7 @@ int IPACM_Lan::add_tcp_syn_flt_rule_l2tp(ipa_ip_type inner_ip_type) } memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(flt_rule_entry)); - + /* no need for hw counters */ if(false == m_filtering.AddFilteringRule(m_pFilteringTable)) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); @@ -6009,3 +6192,147 @@ int IPACM_Lan::add_tcp_syn_flt_rule_l2tp(ipa_ip_type inner_ip_type) free(m_pFilteringTable); return IPACM_SUCCESS; } + +int IPACM_Lan::add_connection(int client_index, int v6_num) +{ + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable = NULL; + int fd; + + mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + /* contruct filter rules to pcie modem */ + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_generate_flt_eq flt_eq; + + IPACMDBG("\n"); + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + + pFilteringTable->commit = 1; + pFilteringTable->global = false; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_rules = (uint8_t)1; + + /* Configuring Filtering Rule */ + 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; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = get_client_memptr(eth_client, client_index)->v6_addr[v6_num][0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = get_client_memptr(eth_client, client_index)->v6_addr[v6_num][1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = get_client_memptr(eth_client, client_index)->v6_addr[v6_num][2]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = get_client_memptr(eth_client, client_index)->v6_addr[v6_num][3]; + 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] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + IPACMDBG_H("ipv6 address got: 0x%x:%x:%x:%x\n", get_client_memptr(eth_client, client_index)->v6_addr[v6_num][0], + get_client_memptr(eth_client, client_index)->v6_addr[v6_num][1], + get_client_memptr(eth_client, client_index)->v6_addr[v6_num][2], + get_client_memptr(eth_client, client_index)->v6_addr[v6_num][3]); + + /* change to network order for modem */ + change_to_network_order(IPA_IP_v6, &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; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + free(pFilteringTable); + return IPACM_FAILURE; + } + + if(0 != ioctl(fd, 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)); + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 0)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(eth_client, client_index)->v6_rt_rule_id[v6_num] = pFilteringTable->rules[0].flt_rule_hdl; + IPACMDBG_H("%d-st client v6_num %d: id handle 0x%x\n", client_index, v6_num, get_client_memptr(eth_client, client_index)->v6_rt_rule_id[v6_num]); +fail: + close(fd); + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Lan::del_connection(int client_index, int v6_num) +{ + int len, res = IPACM_SUCCESS; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + + struct ipa_flt_rule_del flt_rule_entry; + + IPACMDBG("\n"); + len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_hdls = (uint8_t)1; + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = get_client_memptr(eth_client, client_index)->v6_rt_rule_id[v6_num]; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + get_client_memptr(eth_client, client_index)->v6_rt_rule_id[v6_num] = 0; + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} diff --git a/ipacm/src/IPACM_Main.cpp b/ipacm/src/IPACM_Main.cpp index 04f8a89..afdf26d 100644 --- a/ipacm/src/IPACM_Main.cpp +++ b/ipacm/src/IPACM_Main.cpp @@ -113,6 +113,12 @@ int ipa_reset(); int ipa_query_wlan_client(); #endif + +/* support ipa-hw-index-counters */ +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO +int ipa_reset_hw_index_counter(); +#endif + #ifdef FEATURE_IPACM_HAL IPACM_OffloadManager* OffloadMng; HAL *hal; @@ -240,6 +246,10 @@ void* ipa_driver_msg_notifier(void *param) #endif struct ipa_get_data_stats_resp_msg_v01 event_data_stats; struct ipa_get_apn_data_stats_resp_msg_v01 event_network_stats; +#ifdef IPA_RT_SUPPORT_COAL + struct ipa_coalesce_info coalesce_info; +#endif + #ifdef FEATURE_IPACM_HAL IPACM_OffloadManager* OffloadMng; #endif @@ -821,6 +831,40 @@ void* ipa_driver_msg_notifier(void *param) evt_data.evt_data = mapping; break; #endif +#ifdef IPA_RT_SUPPORT_COAL + case IPA_COALESCE_ENABLE: + memcpy(&coalesce_info, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_coalesce_info)); + IPACMDBG_H("Received IPA_COALESCE_ENABLE qmap-id:%d tcp:%d, udp%d\n", + coalesce_info.qmap_id, coalesce_info.tcp_enable, coalesce_info.udp_enable); + if (coalesce_info.qmap_id >=IPA_MAX_NUM_SW_PDNS) + { + IPACMERR("qmap_id (%d) beyond the Max range (%d), abort\n", + coalesce_info.qmap_id, IPA_MAX_NUM_SW_PDNS); + return NULL; + } + IPACM_Wan::coalesce_config(coalesce_info.qmap_id, coalesce_info.tcp_enable, coalesce_info.udp_enable); + /* Notify all LTE instance to do RSC configuration */ + evt_data.event = IPA_COALESCE_NOTICE; + evt_data.evt_data = NULL; + break; + + case IPA_COALESCE_DISABLE: + memcpy(&coalesce_info, buffer + sizeof(struct ipa_msg_meta), sizeof(struct ipa_coalesce_info)); + IPACMDBG_H("Received IPA_COALESCE_DISABLE qmap-id:%d tcp:%d, udp%d\n", + coalesce_info.qmap_id, coalesce_info.tcp_enable, coalesce_info.udp_enable); + if (coalesce_info.qmap_id >=IPA_MAX_NUM_SW_PDNS) + { + IPACMERR("qmap_id (%d) beyond the Max range (%d), abort\n", + coalesce_info.qmap_id, IPA_MAX_NUM_SW_PDNS); + return NULL; + } + IPACM_Wan::coalesce_config(coalesce_info.qmap_id, false, false); + /* Notify all LTE instance to do RSC configuration */ + evt_data.event = IPA_COALESCE_NOTICE; + evt_data.evt_data = NULL; + break; +#endif + default: IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type); continue; @@ -894,6 +938,11 @@ int main(int argc, char **argv) ipa_reset(); #endif +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + IPACMDBG_H("Configure IPA-HW index-counter\n"); + ipa_reset_hw_index_counter(); +#endif + neigh = new IPACM_Neighbor(); ifacemgr = new IPACM_IfaceManager(); #ifdef FEATURE_IPACM_HAL @@ -912,6 +961,8 @@ int main(int argc, char **argv) IPACMDBG_H("Staring IPA main\n"); IPACMDBG_H("ipa_cmdq_successful\n"); + /* reset coalesce settings */ + IPACM_Wan::coalesce_config_reset(); RegisterForSignals(); @@ -1120,3 +1171,51 @@ int ipa_reset() return IPACM_SUCCESS; } #endif + +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO +int ipa_reset_hw_index_counter() +{ + int fd = -1; + struct ipa_ioc_flt_rt_counter_alloc fnr_counters; + struct ipa_ioc_fnr_index_info fnr_info; + + if ((fd = open(IPA_DEVICE_NAME, O_RDWR)) < 0) { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + return IPACM_FAILURE; + } + + memset(&fnr_counters, 0, sizeof(fnr_counters)); + fnr_counters.hw_counter.num_counters = 4; + fnr_counters.hw_counter.allow_less = false; + fnr_counters.sw_counter.num_counters = 4; + fnr_counters.sw_counter.allow_less = false; + IPACMDBG_H("Allocating %d hw counters and %d sw counters\n", + fnr_counters.hw_counter.num_counters, fnr_counters.sw_counter.num_counters); + + if (ioctl(fd, IPA_IOC_FNR_COUNTER_ALLOC, &fnr_counters) < 0) { + IPACMERR("IPA_IOC_FNR_COUNTER_ALLOC call failed: %s \n", strerror(errno)); + close(fd); + return IPACM_FAILURE; + } + + IPACMDBG_H("hw-counter start offset %d, sw-counter start offset %d\n", + fnr_counters.hw_counter.start_id, fnr_counters.sw_counter.start_id); + IPACM_Iface::ipacmcfg->hw_fnr_stats_support = true; + IPACM_Iface::ipacmcfg->hw_counter_offset = fnr_counters.hw_counter.start_id; + IPACM_Iface::ipacmcfg->sw_counter_offset = fnr_counters.sw_counter.start_id; + + /* set FNR counter info */ + memset(&fnr_info, 0, sizeof(fnr_info)); + fnr_info.hw_counter_offset = fnr_counters.hw_counter.start_id; + fnr_info.sw_counter_offset = fnr_counters.sw_counter.start_id; + + if (ioctl(fd, IPA_IOC_SET_FNR_COUNTER_INFO, &fnr_info) < 0) { + IPACMERR("IPA_IOC_SET_FNR_COUNTER_INFO call failed: %s \n", strerror(errno)); + close(fd); + return IPACM_FAILURE; + } + + close(fd); + return IPACM_SUCCESS; +} +#endif diff --git a/ipacm/src/IPACM_OffloadManager.cpp b/ipacm/src/IPACM_OffloadManager.cpp index 1359d49..7919413 100644 --- a/ipacm/src/IPACM_OffloadManager.cpp +++ b/ipacm/src/IPACM_OffloadManager.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. +Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -51,6 +51,7 @@ const char *IPACM_OffloadManager::DEVICE_NAME = "/dev/wwan_ioctl"; /* NatApp class Implementation */ IPACM_OffloadManager *IPACM_OffloadManager::pInstance = NULL; +int IPACM_OffloadManager::num_offload_v4_tethered_iface = 0; IPACM_OffloadManager::IPACM_OffloadManager() { @@ -237,44 +238,49 @@ RET IPACM_OffloadManager::addDownstream(const char * downstream_name, const Pref /* copy to the cache */ for(int i = 0; i < MAX_EVENT_CACHE ;i++) { - if(event_cache[latest_cache_index].valid == false) + if (latest_cache_index >= 0) { - //do the copy - event_cache[latest_cache_index].valid = true; - event_cache[latest_cache_index].event = IPA_DOWNSTREAM_ADD; - memcpy(event_cache[latest_cache_index].dev_name, downstream_name, sizeof(event_cache[latest_cache_index].dev_name)); - memcpy(&event_cache[latest_cache_index].prefix_cache, &prefix, sizeof(event_cache[latest_cache_index].prefix_cache)); - if (prefix.fam == V4) { - IPACMDBG_H("cache event(%d) subnet info v4Addr (%x) v4Mask (%x) dev(%s) on entry (%d)\n", - event_cache[latest_cache_index].event, - event_cache[latest_cache_index].prefix_cache.v4Addr, - event_cache[latest_cache_index].prefix_cache.v4Mask, - event_cache[latest_cache_index].dev_name, - latest_cache_index); - } else { - IPACMDBG_H("cache event (%d) v6Addr: %08x:%08x:%08x:%08x \n", - event_cache[latest_cache_index].event, - event_cache[latest_cache_index].prefix_cache.v6Addr[0], - event_cache[latest_cache_index].prefix_cache.v6Addr[1], - event_cache[latest_cache_index].prefix_cache.v6Addr[2], - event_cache[latest_cache_index].prefix_cache.v6Addr[3]); - IPACMDBG_H("subnet v6Mask: %08x:%08x:%08x:%08x dev(%s) on entry(%d), \n", - event_cache[latest_cache_index].prefix_cache.v6Mask[0], - event_cache[latest_cache_index].prefix_cache.v6Mask[1], - event_cache[latest_cache_index].prefix_cache.v6Mask[2], - event_cache[latest_cache_index].prefix_cache.v6Mask[3], - event_cache[latest_cache_index].dev_name, - latest_cache_index); + if(event_cache[latest_cache_index].valid == false) + { + //do the copy + event_cache[latest_cache_index].valid = true; + event_cache[latest_cache_index].event = IPA_DOWNSTREAM_ADD; + memcpy(event_cache[latest_cache_index].dev_name, downstream_name, + sizeof(event_cache[latest_cache_index].dev_name)); + memcpy(&event_cache[latest_cache_index].prefix_cache, &prefix, + sizeof(event_cache[latest_cache_index].prefix_cache)); + if (prefix.fam == V4) { + IPACMDBG_H("cache event(%d) subnet info v4Addr (%x) v4Mask (%x) dev(%s) on entry (%d)\n", + event_cache[latest_cache_index].event, + event_cache[latest_cache_index].prefix_cache.v4Addr, + event_cache[latest_cache_index].prefix_cache.v4Mask, + event_cache[latest_cache_index].dev_name, + latest_cache_index); + } else { + IPACMDBG_H("cache event (%d) v6Addr: %08x:%08x:%08x:%08x \n", + event_cache[latest_cache_index].event, + event_cache[latest_cache_index].prefix_cache.v6Addr[0], + event_cache[latest_cache_index].prefix_cache.v6Addr[1], + event_cache[latest_cache_index].prefix_cache.v6Addr[2], + event_cache[latest_cache_index].prefix_cache.v6Addr[3]); + IPACMDBG_H("subnet v6Mask: %08x:%08x:%08x:%08x dev(%s) on entry(%d), \n", + event_cache[latest_cache_index].prefix_cache.v6Mask[0], + event_cache[latest_cache_index].prefix_cache.v6Mask[1], + event_cache[latest_cache_index].prefix_cache.v6Mask[2], + event_cache[latest_cache_index].prefix_cache.v6Mask[3], + event_cache[latest_cache_index].dev_name, + latest_cache_index); + } + latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE; + break; } latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE; - break; } - latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE; if(i == MAX_EVENT_CACHE - 1) { IPACMDBG_H(" run out of event cache (%d)\n", i); - return FAIL_HARDWARE; - } + return FAIL_HARDWARE; + } } return SUCCESS; @@ -412,37 +418,43 @@ RET IPACM_OffloadManager::setUpstream(const char *upstream_name, const Prefix& g /* copy to the cache */ for(int i = 0; i < MAX_EVENT_CACHE ;i++) { - if(event_cache[latest_cache_index].valid == false) + if (latest_cache_index >= 0) { - //do the copy - event_cache[latest_cache_index].valid = true; - event_cache[latest_cache_index].event = IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT; - memcpy(event_cache[latest_cache_index].dev_name, upstream_name, sizeof(event_cache[latest_cache_index].dev_name)); - memcpy(&event_cache[latest_cache_index].prefix_cache, &gw_addr_v4, sizeof(event_cache[latest_cache_index].prefix_cache)); - memcpy(&event_cache[latest_cache_index].prefix_cache_v6, &gw_addr_v6, sizeof(event_cache[latest_cache_index].prefix_cache_v6)); - if (gw_addr_v4.fam == V4) { - IPACMDBG_H("cache event(%d) ipv4 gateway: (%x) dev(%s) on entry (%d)\n", - event_cache[latest_cache_index].event, - event_cache[latest_cache_index].prefix_cache.v4Addr, - event_cache[latest_cache_index].dev_name, - latest_cache_index); - } - - if (gw_addr_v6.fam == V6) - { - IPACMDBG_H("cache event (%d) ipv6 gateway: %08x:%08x:%08x:%08x dev(%s) on entry(%d)\n", - event_cache[latest_cache_index].event, - event_cache[latest_cache_index].prefix_cache_v6.v6Addr[0], - event_cache[latest_cache_index].prefix_cache_v6.v6Addr[1], - event_cache[latest_cache_index].prefix_cache_v6.v6Addr[2], - event_cache[latest_cache_index].prefix_cache_v6.v6Addr[3], - event_cache[latest_cache_index].dev_name, - latest_cache_index); + if(event_cache[latest_cache_index].valid == false) + { + //do the copy + event_cache[latest_cache_index].valid = true; + event_cache[latest_cache_index].event = IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT; + memcpy(event_cache[latest_cache_index].dev_name, upstream_name, + sizeof(event_cache[latest_cache_index].dev_name)); + memcpy(&event_cache[latest_cache_index].prefix_cache, &gw_addr_v4, + sizeof(event_cache[latest_cache_index].prefix_cache)); + memcpy(&event_cache[latest_cache_index].prefix_cache_v6, &gw_addr_v6, + sizeof(event_cache[latest_cache_index].prefix_cache_v6)); + if (gw_addr_v4.fam == V4) { + IPACMDBG_H("cache event(%d) ipv4 gateway: (%x) dev(%s) on entry (%d)\n", + event_cache[latest_cache_index].event, + event_cache[latest_cache_index].prefix_cache.v4Addr, + event_cache[latest_cache_index].dev_name, + latest_cache_index); + } + + if (gw_addr_v6.fam == V6) + { + IPACMDBG_H("cache event (%d) ipv6 gateway: %08x:%08x:%08x:%08x dev(%s) on entry(%d)\n", + event_cache[latest_cache_index].event, + event_cache[latest_cache_index].prefix_cache_v6.v6Addr[0], + event_cache[latest_cache_index].prefix_cache_v6.v6Addr[1], + event_cache[latest_cache_index].prefix_cache_v6.v6Addr[2], + event_cache[latest_cache_index].prefix_cache_v6.v6Addr[3], + event_cache[latest_cache_index].dev_name, + latest_cache_index); + } + latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE; + break; } latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE; - break; } - latest_cache_index = (latest_cache_index + 1)% MAX_EVENT_CACHE; if(i == MAX_EVENT_CACHE - 1) { IPACMDBG_H(" run out of event cache (%d) \n", i); @@ -566,6 +578,7 @@ RET IPACM_OffloadManager::stopAllOffload() memset(event_cache, 0, MAX_EVENT_CACHE*sizeof(framework_event_cache)); latest_cache_index = 0; valid_ifaces.clear(); + IPACM_OffloadManager::num_offload_v4_tethered_iface = 0; return result; } @@ -590,7 +603,7 @@ RET IPACM_OffloadManager::setQuota(const char * upstream_name /* upstream */, ui return FAIL_INPUT_CHECK; } - IPACMDBG_H("SET_DATA_QUOTA %s %llu", quota.interface_name, (long long)mb); + IPACMDBG_H("SET_DATA_QUOTA %s %llu\n", quota.interface_name, (long long)mb); rc = ioctl(fd, WAN_IOC_SET_DATA_QUOTA, "a); @@ -765,12 +778,14 @@ IPACM_OffloadManager* IPACM_OffloadManager::GetInstance() bool IPACM_OffloadManager::search_framwork_cache(char * interface_name) { bool rel = false; + bool cache_need = false; /* IPACM needs to kee old FDs, can't clear */ IPACMDBG_H("check netdev(%s)\n", interface_name); for(int i = 0; i < MAX_EVENT_CACHE ;i++) { + cache_need = false; if(event_cache[i].valid == true) { //do the compare @@ -780,14 +795,40 @@ bool IPACM_OffloadManager::search_framwork_cache(char * interface_name) { IPACMDBG_H("found netdev (%s) in entry (%d) with event (%d)\n", interface_name, i, event_cache[i].event); /* post event again */ - if (event_cache[i].event == IPA_DOWNSTREAM_ADD) + if (event_cache[i].event == IPA_DOWNSTREAM_ADD) { + /* check if downsteam netdev driver finished its configuration on IPA-HW for ipv4 and ipv6 */ + if (event_cache[i].prefix_cache.fam == V4 && IPACM_Iface::ipacmcfg->CheckNatIfaces(event_cache[i].dev_name, IPA_IP_v4)) + cache_need = true; + if (event_cache[i].prefix_cache.fam == V6 && IPACM_Iface::ipacmcfg->CheckNatIfaces(event_cache[i].dev_name, IPA_IP_v6)) + cache_need = true; + if (cache_need) { + IPACMDBG_H("still need cache (%d), index (%d) ip-family (%d)\n", cache_need, i, event_cache[i].prefix_cache.fam); + break; + } else { + IPACMDBG_H("no need cache (%d), handling it event (%d)\n", cache_need, event_cache[i].event); addDownstream(interface_name, event_cache[i].prefix_cache); - else if (event_cache[i].event == IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT) + } + } else if (event_cache[i].event == IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT) { + /* check if upstream netdev driver finished its configuration on IPA-HW for ipv4 and ipv6 */ + if (event_cache[i].prefix_cache.fam == V4 && IPACM_Iface::ipacmcfg->CheckNatIfaces(event_cache[i].dev_name, IPA_IP_v4)) + cache_need = true; + if (event_cache[i].prefix_cache_v6.fam == V6 && IPACM_Iface::ipacmcfg->CheckNatIfaces(event_cache[i].dev_name, IPA_IP_v6)) + cache_need = true; + if (cache_need) { + IPACMDBG_H("still need cache (%d), index (%d)\n", cache_need, i); + break; + } else { + IPACMDBG_H("no need cache (%d), handling it event (%d)\n", cache_need, event_cache[i].event); setUpstream(interface_name, event_cache[i].prefix_cache, event_cache[i].prefix_cache_v6); - else - IPACMERR("wrong event cached (%d)", event_cache[i].event); + } + } else { + IPACMERR("wrong event cached (%d) index (%d)\n", event_cache[i].event, i); + } + + /* reset entry */ event_cache[i].valid = false; rel = true; + IPACMDBG_H("reset entry (%d)", i); } } } diff --git a/ipacm/src/IPACM_Routing.cpp b/ipacm/src/IPACM_Routing.cpp index 2a2555a..654a0f9 100644 --- a/ipacm/src/IPACM_Routing.cpp +++ b/ipacm/src/IPACM_Routing.cpp @@ -112,6 +112,115 @@ bool IPACM_Routing::AddRoutingRule(struct ipa_ioc_add_rt_rule *ruleTable) return true; } +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO +bool IPACM_Routing::AddRoutingRule_hw_index(struct ipa_ioc_add_rt_rule *ruleTable, int hw_counter_index) +{ + int retval = 0, cnt = 0, len = 0; + struct ipa_ioc_add_rt_rule_v2 *ruleTable_v2; + struct ipa_rt_rule_add_v2 rt_rule_entry; + bool ret = true; + + IPACMDBG("Printing routing add attributes\n"); + IPACMDBG("ip type: %d\n", ruleTable->ip); + IPACMDBG("rt tbl type: %s\n", ruleTable->rt_tbl_name); + IPACMDBG("Number of rules: %d\n", ruleTable->num_rules); + IPACMDBG("commit value: %d\n", ruleTable->commit); + + /* change to v2 format*/ + len = sizeof(struct ipa_ioc_add_rt_rule_v2); + ruleTable_v2 = (struct ipa_ioc_add_rt_rule_v2*)malloc(len); + if (ruleTable_v2 == NULL) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule_v2 memory...\n"); + return false; + } + memset(ruleTable_v2, 0, len); + ruleTable_v2->rules = (uint64_t)calloc(ruleTable->num_rules, sizeof(struct ipa_rt_rule_add_v2)); + if (!ruleTable_v2->rules) { + IPACMERR("Failed to allocate memory for routing rules\n"); + ret = false; + goto fail_tbl; + } + + ruleTable_v2->commit = ruleTable->commit; + ruleTable_v2->ip = ruleTable->ip; + ruleTable_v2->num_rules = ruleTable->num_rules; + ruleTable_v2->rule_add_size = sizeof(struct ipa_rt_rule_add_v2); + memcpy(ruleTable_v2->rt_tbl_name, + ruleTable->rt_tbl_name, + sizeof(ruleTable_v2->rt_tbl_name)); + + for (cnt=0; cnt < ruleTable->num_rules; cnt++) + { + memset(&rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add_v2)); + rt_rule_entry.at_rear = ruleTable->rules[cnt].at_rear; + rt_rule_entry.rule.dst = ruleTable->rules[cnt].rule.dst; + rt_rule_entry.rule.hdr_hdl = ruleTable->rules[cnt].rule.hdr_hdl; + rt_rule_entry.rule.hdr_proc_ctx_hdl = ruleTable->rules[cnt].rule.hdr_proc_ctx_hdl; + rt_rule_entry.rule.max_prio = ruleTable->rules[cnt].rule.max_prio; + rt_rule_entry.rule.hashable = ruleTable->rules[cnt].rule.hashable; + rt_rule_entry.rule.retain_hdr = ruleTable->rules[cnt].rule.retain_hdr; + rt_rule_entry.rule.coalesce = ruleTable->rules[cnt].rule.coalesce; + memcpy(&rt_rule_entry.rule.attrib, + &ruleTable->rules[cnt].rule.attrib, + sizeof(rt_rule_entry.rule.attrib)); + IPACMDBG("RT rule:%d attrib mask: 0x%x\n", cnt, + ruleTable->rules[cnt].rule.attrib.attrib_mask); + /* 0 means disable hw-counter-sats */ + if (hw_counter_index != 0) + { + rt_rule_entry.rule.enable_stats = 1; + rt_rule_entry.rule.cnt_idx = hw_counter_index; + } + + /* copy to v2 table*/ + memcpy((void *)(ruleTable_v2->rules + (cnt * sizeof(struct ipa_rt_rule_add_v2))), + &rt_rule_entry, sizeof(rt_rule_entry)); + } + + retval = ioctl(m_fd, IPA_IOC_ADD_RT_RULE_V2, ruleTable_v2); + if (retval != 0) + { + IPACMERR("Failed adding Routing rule %pK\n", ruleTable_v2); + PERROR("unable to add routing rule:"); + + for (int cnt = 0; cnt < ruleTable_v2->num_rules; cnt++) + { + if (((struct ipa_rt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0) + { + IPACMERR("Adding Routing rule:%d failed with status:%d\n", + cnt, ((struct ipa_rt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status); + } + } + ret = false; + goto fail_rule; + } + + /* copy results from v2 to v1 format */ + for (int cnt = 0; cnt < ruleTable->num_rules; cnt++) + { + /* copy status to v1 format */ + ruleTable->rules[cnt].status = ((struct ipa_rt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status; + ruleTable->rules[cnt].rt_rule_hdl = ((struct ipa_rt_rule_add_v2 *)ruleTable_v2->rules)[cnt].rt_rule_hdl; + + if(((struct ipa_rt_rule_add_v2 *)ruleTable_v2->rules)[cnt].status != 0) + { + IPACMERR("Adding Routing rule:%d failed with status:%d\n", + cnt, ((struct ipa_rt_rule_add_v2 *) ruleTable_v2->rules)[cnt].status); + } + } + IPACMDBG("Added Routing rule %pK\n", ruleTable_v2); +fail_rule: + if((void *)ruleTable_v2->rules != NULL) + free((void *)ruleTable_v2->rules); +fail_tbl: + if (ruleTable_v2 != NULL) + free(ruleTable_v2); + return ret; +} +#endif //IPA_IOCTL_SET_FNR_COUNTER_INFO + + bool IPACM_Routing::DeleteRoutingRule(struct ipa_ioc_del_rt_rule *ruleTable) { int retval = 0; diff --git a/ipacm/src/IPACM_Wan.cpp b/ipacm/src/IPACM_Wan.cpp index 278f9ac..db0304a 100644 --- a/ipacm/src/IPACM_Wan.cpp +++ b/ipacm/src/IPACM_Wan.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, 2018 The Linux Foundation. All rights reserved. +Copyright (c) 2013-2019 The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -69,7 +69,7 @@ struct ipa_flt_rule_add IPACM_Wan::flt_rule_v6[IPA_MAX_FLT_RULE]; char IPACM_Wan::wan_up_dev_name[IF_NAME_LEN]; -bool IPACM_Wan::backhaul_is_sta_mode = false; +ipacm_wan_iface_type IPACM_Wan::backhaul_mode = Q6_WAN; bool IPACM_Wan::is_ext_prop_set = false; int IPACM_Wan::num_ipv4_modem_pdn = 0; @@ -77,6 +77,9 @@ int IPACM_Wan::num_ipv6_modem_pdn = 0; bool IPACM_Wan::embms_is_on = false; bool IPACM_Wan::backhaul_is_wan_bridge = false; +bool IPACM_Wan::is_xlat = false; + +ipacm_coalesce IPACM_Wan::coalesce_enable_info[IPA_MAX_NUM_SW_PDNS]; uint32_t IPACM_Wan::backhaul_ipv6_prefix[2]; @@ -107,7 +110,6 @@ IPACM_Wan::IPACM_Wan(int iface_index, wan_route_rule_v6_hdl_a5 = (uint32_t *)calloc(iface_query->num_tx_props, sizeof(uint32_t)); IPACMDBG_H("IPACM->IPACM_Wan(%d) constructor: Tx:%d\n", ipa_if_num, iface_query->num_tx_props); } - m_is_sta_mode = is_sta_mode; wan_v4_addr_set = false; wan_v4_addr_gw_set = false; @@ -132,15 +134,41 @@ IPACM_Wan::IPACM_Wan(int iface_index, header_name_count = 0; memset(invalid_mac, 0, sizeof(invalid_mac)); - is_xlat = false; + is_xlat_local = false; hdr_hdl_dummy_v6 = 0; hdr_proc_hdl_dummy_v6 = 0; is_default_gateway = false; m_fd_ipa = 0; wan_client_len = 0; + m_is_sta_mode = is_sta_mode; if(iface_query != NULL) { + IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); + + if(is_sta_mode == Q6_WAN) + { + query_ext_prop(); + + if ((iface_query->num_ext_props == 1) && ((ext_prop != NULL) && ext_prop->ext[0].ip == IPA_IP_MAX)) + { + /* only has one ext properties with IP_MAX type, will be the mhi-modem */ + IPACMDBG_H("One extended property for iface %s, replace %d to Q6_MHI_WAN\n", dev_name, is_sta_mode); + m_is_sta_mode = Q6_MHI_WAN; + } + else + { + IPACMDBG_H("The new WAN interface is modem.\n"); + m_is_sta_mode = is_sta_mode; + is_default_gateway = false; + } + } + else + { + m_is_sta_mode = is_sta_mode; + IPACMDBG_H("The new WAN interface is WLAN STA.\n"); + } + wan_client_len = (sizeof(ipa_wan_client)) + (iface_query->num_tx_props * sizeof(wan_client_rt_hdl)); wan_client = (ipa_wan_client *)calloc(IPA_MAX_NUM_WAN_CLIENTS, wan_client_len); if (wan_client == NULL) @@ -148,19 +176,11 @@ IPACM_Wan::IPACM_Wan(int iface_index, IPACMERR("unable to allocate memory\n"); return; } - IPACMDBG_H("index:%d constructor: Tx properties:%d\n", iface_index, iface_query->num_tx_props); - } - - - if(m_is_sta_mode == Q6_WAN) - { - IPACMDBG_H("The new WAN interface is modem.\n"); - is_default_gateway = false; - query_ext_prop(); } else { - IPACMDBG_H("The new WAN interface is WLAN STA.\n"); + IPACMDBG_H("iface_query is empty.\n"); + return; } m_fd_ipa = open(IPA_DEVICE_NAME, O_RDWR); @@ -207,6 +227,7 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) struct ipa_ioc_add_flt_rule *flt_rule; struct ipa_flt_rule_add flt_rule_entry; struct ipa_ioc_get_hdr hdr; + bool result; const int NUM_RULES = 1; uint32_t num_ipv6_addr; @@ -252,29 +273,11 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) rt_rule->commit = 1; rt_rule->num_rules = NUM_RULES; rt_rule->ip = data->iptype; + /* setup RT rule for v6_lan table*/ strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); rt_rule_entry = &rt_rule->rules[0]; - if(m_is_sta_mode == Q6_WAN) - { - strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); - hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; - if(m_header.GetHeaderHandle(&hdr) == false) - { - IPACMERR("Failed to get QMAP header.\n"); - return IPACM_FAILURE; - } - rt_rule_entry->rule.hdr_hdl = hdr.hdl; - } rt_rule_entry->at_rear = false; - if(m_is_sta_mode == Q6_WAN) - { - rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; - } - else - { - rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; - } rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; @@ -291,6 +294,90 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) #ifdef FEATURE_IPA_V3 rt_rule_entry->rule.hashable = false; #endif + if(m_is_sta_mode == Q6_WAN) + { + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + /* legacy default v4 rt-rule */ +#ifdef IPA_RT_SUPPORT_COAL + rt_rule_entry->rule.coalesce = false; +#endif + /* legacy default v6 rt-rule */ + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; + + /* setup same rule for v6_wan table*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; + + IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n", + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1], + MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6, + MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1); + /* RSC TCP rule*/ + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d), entry %d", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable, + 2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6); + /* RSB UDP rule*/ + rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; +#endif if (false == m_routing.AddRoutingRule(rt_rule)) { IPACMERR("Routing rule addition failed!\n"); @@ -299,6 +386,27 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) } else if (rt_rule_entry->status) { + IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d) entry %d", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable, + 2*MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1); + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + /* legacy default v6 rt-rule */ + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); res = rt_rule_entry->status; goto fail; @@ -321,9 +429,12 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) } dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1] = rt_rule_entry->rt_rule_hdl; - IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, num_dft_rt_v6: %d \n", + IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n", dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6], - dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1],num_dft_rt_v6); + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1], + MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6, + MAX_DEFAULT_v4_ROUTE_RULES + 2*num_dft_rt_v6+1); + } /* add default filtering rules when wan-iface get global v6-prefix */ if (num_dft_rt_v6 == 1) @@ -335,6 +446,11 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) IPACMDBG_H("Now the number of modem ipv6 pdn is %d.\n", num_ipv6_modem_pdn); init_fl_rule_ex(data->iptype); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + 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); + } else { init_fl_rule(data->iptype); @@ -383,8 +499,20 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = 0xFFFFFFFF; flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; memcpy(&(flt_rule->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(flt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(flt_rule); + } +#else + result = m_filtering.AddFilteringRule(flt_rule); +#endif - if (m_filtering.AddFilteringRule(flt_rule) == false) + if (result == false) { IPACMERR("Error Adding Filtering rule, aborting...\n"); free(flt_rule); @@ -421,6 +549,21 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) else { IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name); + /* Delete default Coalese v4 RT rule */ + if (m_is_sta_mode == Q6_WAN) { + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing old RSC TCP RT rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false) + { + IPACMERR("Routing old RSB UDP RT rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + } /* 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) @@ -446,30 +589,80 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) rt_rule->num_rules = NUM_RULES; rt_rule->ip = data->iptype; rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + /* still need setup v4 default routing rule to A5*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif if(m_is_sta_mode == Q6_WAN) { + /* query qmap header*/ strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; if(m_header.GetHeaderHandle(&hdr) == false) { IPACMERR("Failed to get QMAP header.\n"); - return IPACM_FAILURE; + res = IPACM_FAILURE; + goto fail; } rt_rule_entry->rule.hdr_hdl = hdr.hdl; rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + /* legacy default v4 rt-rule */ +#ifdef IPA_RT_SUPPORT_COAL + rt_rule_entry->rule.coalesce = false; +#endif + /* legacy default v4 rt-rule */ + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; } + dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); + /* RSC TCP rule*/ + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; + +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable) + rt_rule_entry->rule.coalesce = true; else + rt_rule_entry->rule.coalesce = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) { - rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; } - rt_rule_entry->at_rear = false; - rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; - /* still need setup v4 default routing rule to A5*/ - strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); - rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; - rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; -#ifdef FEATURE_IPA_V3 - rt_rule_entry->rule.hashable = false; + dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[0], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable); + + /* RSB UDP rule*/ + rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; #endif if (false == m_routing.AddRoutingRule(rt_rule)) { @@ -479,14 +672,35 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) } else if (rt_rule_entry->status) { + IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[1], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable); + } + else + { + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + /* legacy default v4 rt-rule */ + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); res = rt_rule_entry->status; goto fail; } dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); - /* initial multicast/broadcast/fragment filter rule */ + } + /* initial multicast/broadcast/fragment filter rule */ /* only do one time */ if(!wan_v4_addr_set) { @@ -498,6 +712,11 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) IPACMDBG_H("Now the number of modem ipv4 pdn is %d.\n", num_ipv4_modem_pdn); init_fl_rule_ex(data->iptype); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v4); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v4); + } else { init_fl_rule(data->iptype); @@ -526,11 +745,231 @@ int IPACM_Wan::handle_addr_evt(ipacm_event_data_addr *data) IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); fail: - free(rt_rule); - + if (rt_rule != NULL) + { + free(rt_rule); + } return res; } +/* handle new_address event */ +int IPACM_Wan::handle_addr_evt_mhi_q6(ipacm_event_data_addr *data) +{ + uint32_t num_ipv6_addr; + int res = IPACM_SUCCESS; + struct ipa_ioc_add_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_add *rt_rule_entry; + struct ipa_ioc_get_hdr hdr; + const int NUM_RULES = 1; + +#ifdef FEATURE_IPACM_HAL + IPACM_OffloadManager* OffloadMng; +#endif + + memset(&hdr, 0, sizeof(hdr)); + if(tx_prop == NULL || rx_prop == NULL) + { + IPACMDBG_H("Either tx or rx property is NULL, return.\n"); + return IPACM_SUCCESS; + } + /* Update the IP Type. */ + config_ip_type(data->iptype); + + if (data->iptype == IPA_IP_v6) + { + for(num_ipv6_addr=0;num_ipv6_addr<num_dft_rt_v6;num_ipv6_addr++) + { + if((ipv6_addr[num_ipv6_addr][0] == data->ipv6_addr[0]) && + (ipv6_addr[num_ipv6_addr][1] == data->ipv6_addr[1]) && + (ipv6_addr[num_ipv6_addr][2] == data->ipv6_addr[2]) && + (ipv6_addr[num_ipv6_addr][3] == data->ipv6_addr[3])) + { + IPACMDBG_H("find matched ipv6 address, index:%d \n", num_ipv6_addr); + return IPACM_SUCCESS; + break; + } + } + + ipv6_addr[num_dft_rt_v6][0] = data->ipv6_addr[0]; + ipv6_addr[num_dft_rt_v6][1] = data->ipv6_addr[1]; + ipv6_addr[num_dft_rt_v6][2] = data->ipv6_addr[2]; + ipv6_addr[num_dft_rt_v6][3] = data->ipv6_addr[3]; + + /* store ipv6 prefix if the ipv6 address is not link local */ + if(is_global_ipv6_addr(data->ipv6_addr)) + { + memcpy(ipv6_prefix, data->ipv6_addr, sizeof(ipv6_prefix)); + } + num_dft_rt_v6++; + if (num_dft_rt_v6 == 1) + { + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) + { + 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 */ + 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)); + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry = &rt_rule->rules[0]; + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + free(rt_rule); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + /* still need setup v4 default routing rule to A5*/ + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + rt_rule_entry->rule.attrib.u.v6.dst_addr[0] = data->ipv6_addr[0]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[1] = data->ipv6_addr[1]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[2] = data->ipv6_addr[2]; + rt_rule_entry->rule.attrib.u.v6.dst_addr[3] = data->ipv6_addr[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; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + ipv6_addr[0][0] = data->ipv6_addr[0]; + ipv6_addr[0][1] = data->ipv6_addr[1]; + ipv6_addr[0][2] = data->ipv6_addr[2]; + ipv6_addr[0][3] = data->ipv6_addr[3]; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + free(rt_rule); + return rt_rule_entry->status; + } + dft_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv6 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[1]); + } + } + else + { + if(wan_v4_addr_set) + { + /* check iface ipv4 same or not */ + if(data->ipv4_addr == wan_v4_addr) + { + IPACMDBG_H("Already setup device (%s) ipv4 and it didn't change(0x%x)\n", dev_name, data->ipv4_addr); + return IPACM_SUCCESS; + } + else + { + IPACMDBG_H(" device (%s) ipv4 addr is changed\n", dev_name); + /* 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 old RT rule deletion failed!\n"); + return IPACM_FAILURE; + } + } + } + /* only do one time */ + if(!wan_v4_addr_set) + { + /* Add Natting iface to IPACM_Config if there is Rx/Tx property */ + if (rx_prop != NULL || tx_prop != NULL) + { + IPACMDBG_H(" Has rx/tx properties registered for iface %s, add for NATTING for ip-family %d \n", dev_name, IPA_IP_v4); + IPACM_Iface::ipacmcfg->AddNatIfaces(dev_name, IPA_IP_v4); + } + + 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)); + + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = data->iptype; + rt_rule_entry = &rt_rule->rules[0]; + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + free(rt_rule); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_LAN_CONS; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + /* still need setup v4 default routing rule to A5*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.attrib.u.v4.dst_addr = data->ipv4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + free(rt_rule); + return IPACM_FAILURE; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + free(rt_rule); + return rt_rule_entry->status; + } + dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); + } + + wan_v4_addr = data->ipv4_addr; + wan_v4_addr_set = true; + IPACMDBG_H("Receved wan ipv4-addr:0x%x\n",wan_v4_addr); + free(rt_rule); + } + +#ifdef FEATURE_IPACM_HAL + /* check if having pending set_upstream cache*/ + OffloadMng = IPACM_OffloadManager::GetInstance(); + if (OffloadMng == NULL) { + IPACMERR("failed to get IPACM_OffloadManager instance !\n"); + } else { + IPACMDBG_H(" check iface %s if having set_upstream cache events\n", dev_name); + OffloadMng->search_framwork_cache(dev_name); + } +#endif + IPACMDBG_H("number of default route rules %d\n", num_dft_rt_v6); + + return res; +} void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { int ipa_interface_index; @@ -565,9 +1004,9 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) ipa_interface_index = IPACM_Iface::iface_ipa_index_query(data->if_index); if ((ipa_interface_index == ipa_if_num) && (m_is_sta_mode == Q6_WAN)) { - is_xlat = true; - IPACMDBG_H("WAN-LTE (%s) link up, iface: %d is_xlat: %d\n", - IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,data->if_index, is_xlat); + is_xlat_local = true; + IPACMDBG_H("WAN-LTE (%s) link up, iface: %d is_xlat_local: %d\n", + IPACM_Iface::ipacmcfg->iface_table[ipa_interface_index].iface_name,data->if_index, is_xlat_local); } break; } @@ -665,6 +1104,15 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) } break; + case IPA_COALESCE_NOTICE: + { + if (m_is_sta_mode == Q6_WAN) + { + IPACMDBG_H("Received IPA_COALESCE_NOTICE (wan_mode:%d)\n", m_is_sta_mode); + handle_coalesce_evt(); + } + } + break; case IPA_LINK_DOWN_EVENT: { ipacm_event_data_fid *data = (ipacm_event_data_fid *)param; @@ -680,7 +1128,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) delete this; return; } - else if (m_is_sta_mode == ECM_WAN) + else if ((m_is_sta_mode == ECM_WAN) || (m_is_sta_mode == Q6_MHI_WAN)) { IPACMDBG_H("Received IPA_LINK_DOWN_EVENT(wan_mode:%d)\n", m_is_sta_mode); /* delete previous instance */ @@ -715,15 +1163,31 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) if( (data->iptype == IPA_IP_v4) || ((data->iptype==IPA_IP_v6) && (num_dft_rt_v6!=MAX_DEFAULT_v6_ROUTE_RULES))) { - IPACMDBG_H("Got IPA_ADDR_ADD_EVENT ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); - handle_addr_evt(data); + if (m_is_sta_mode == Q6_MHI_WAN) + { + IPACMDBG_H("Got handle_addr_evt_mhi_q6 ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); + handle_addr_evt_mhi_q6(data); + } + else + { + IPACMDBG_H("Got handle_addr_evt ip-family:%d, v6 num %d: \n",data->iptype,num_dft_rt_v6); + handle_addr_evt(data); + } /* checking if SW-RT_enable */ if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true && m_is_sta_mode != Q6_WAN) { /* handle software routing enable event*/ IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); - handle_software_routing_enable(); + + if(m_is_sta_mode == Q6_MHI_WAN) + { + handle_software_routing_enable(true); + } + else + { + handle_software_routing_enable(false); + } } } @@ -763,7 +1227,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) #endif if (active_v4 == false) { - handle_route_add_evt(data->iptype); //sky + handle_route_add_evt(data->iptype); } } #ifdef FEATURE_IPA_ANDROID @@ -824,6 +1288,11 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v4); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + /* only need cleanup rt-rule*/ + handle_route_del_evt(IPA_IP_v4); + } else { del_dft_firewall_rules(IPA_IP_v4); @@ -840,6 +1309,11 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v6); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + /* only need cleanup rt-rule*/ + handle_route_del_evt(IPA_IP_v6); + } else { del_dft_firewall_rules(IPA_IP_v6); @@ -889,6 +1363,12 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v4); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + /* only need cleanup rt-rule*/ + del_dft_firewall_rules(IPA_IP_v4); + handle_route_del_evt(IPA_IP_v4); + } else { del_dft_firewall_rules(IPA_IP_v4); @@ -918,6 +1398,13 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v6); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + /* only need cleanup rt-rule*/ + del_dft_firewall_rules(IPA_IP_v6); + handle_route_del_evt(IPA_IP_v6); + } + else { del_dft_firewall_rules(IPA_IP_v6); @@ -962,7 +1449,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) handle_sta_header_add_evt(); handle_route_add_evt(data->iptype); /* Add IPv6 routing table if XLAT is enabled */ - if(is_xlat && (m_is_sta_mode == Q6_WAN) && (active_v6 == false)) + if(is_xlat_local && (m_is_sta_mode == Q6_WAN) && (active_v6 == false)) { IPACMDBG_H("XLAT enabled: adding IPv6 routing table dev (%s)\n", dev_name); handle_route_add_evt(IPA_IP_v6); @@ -1051,7 +1538,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) install_wan_filtering_rule(false); handle_route_del_evt_ex(IPA_IP_v4); - if(is_xlat && active_v6 == true) + if(is_xlat_local && active_v6 == true) { IPACMDBG_H("XLAT enabled: Delete IPv6 routing table dev (%s)\n", dev_name); del_wan_firewall_rule(IPA_IP_v6); @@ -1153,9 +1640,13 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) { install_wan_filtering_rule(true); } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + handle_software_routing_enable(true); + } else { - handle_software_routing_enable(); + handle_software_routing_enable(false); } break; @@ -1168,9 +1659,13 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) install_wan_filtering_rule(false); softwarerouting_act = false; } + else if(m_is_sta_mode == Q6_MHI_WAN) + { + handle_software_routing_disable(true); + } else { - handle_software_routing_disable(); + handle_software_routing_disable(false); } break; @@ -1228,7 +1723,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) break; case IPA_WLAN_SWITCH_TO_SCC: - if(IPACM_Wan::backhaul_is_sta_mode == true) + if(IPACM_Wan::backhaul_mode == WLAN_WAN) { IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_SCC\n"); if(ip_type == IPA_IP_MAX) @@ -1247,7 +1742,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) break; case IPA_WLAN_SWITCH_TO_MCC: - if(IPACM_Wan::backhaul_is_sta_mode == true) + if(IPACM_Wan::backhaul_mode == WLAN_WAN) { IPACMDBG_H("Received IPA_WLAN_SWITCH_TO_MCC\n"); if(ip_type == IPA_IP_MAX) @@ -1266,7 +1761,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param) break; #ifdef FEATURE_IPACM_HAL /* WA for WLAN to clean up NAT instance during SSR */ - case IPA_SSR_NOTICE: //sky + 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) @@ -1293,6 +1788,7 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) const int NUM = 1; ipacm_cmd_q_data evt_data; struct ipa_ioc_get_hdr hdr; + bool result; #ifdef WAN_IOC_NOTIFY_WAN_STATE //resolve compile issue on 4.9 kernel struct wan_ioctl_notify_wan_state wan_state; int fd_wwan_ioctl; @@ -1322,25 +1818,9 @@ 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); - if (m_is_sta_mode !=Q6_WAN) - { - IPACM_Wan::backhaul_is_sta_mode = true; - if((iptype==IPA_IP_v4) && (header_set_v4 != true)) - { - header_partial_default_wan_v4 = true; - IPACMDBG_H("STA ipv4-header haven't constructed \n"); - return IPACM_SUCCESS; - } - else if((iptype==IPA_IP_v6) && (header_set_v6 != true)) - { - header_partial_default_wan_v6 = true; - IPACMDBG_H("STA ipv6-header haven't constructed \n"); - return IPACM_SUCCESS; - } - } - else + if (m_is_sta_mode ==Q6_WAN) { - IPACM_Wan::backhaul_is_sta_mode = false; + IPACM_Wan::backhaul_mode = m_is_sta_mode; IPACMDBG_H("reset backhaul to LTE \n"); if (iface_query != NULL && iface_query->num_ext_props > 0) @@ -1362,53 +1842,64 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) return IPACM_FAILURE; } } -#if 0 - for (cnt=0; cnt<tx_prop->num_tx_props; cnt++) - { - if(tx_prop->tx[cnt].ip==iptype) - break; - } - - if(tx_prop->tx[cnt].hdr_name != NULL) + else if (m_is_sta_mode == Q6_MHI_WAN) { - memset(&sCopyHeader, 0, sizeof(sCopyHeader)); - memcpy(sCopyHeader.name, - tx_prop->tx[cnt].hdr_name, - sizeof(sCopyHeader.name)); - - IPACMDBG_H("header name: %s\n", sCopyHeader.name); - if (m_header.CopyHeader(&sCopyHeader) == false) - { - IPACMERR("ioctl copy header failed"); - return IPACM_FAILURE; - } - IPACMDBG_H("header length: %d, paritial: %d\n", sCopyHeader.hdr_len, sCopyHeader.is_partial); - if(sCopyHeader.is_partial) - { - IPACMDBG_H("Not setup default WAN routing rules cuz the header is not complete\n"); - if(iptype==IPA_IP_v4) + if (iface_query != NULL && iface_query->num_ext_props > 0) + { + /* treat Q6_MHI_WAN as STA mode also */ + IPACMDBG_H("Q6-MHI ipv4/v6-header already constructed \n"); + IPACM_Wan::backhaul_mode = m_is_sta_mode; + IPACMDBG_H("Setting up QMAP ID %d.\n", ext_prop->ext[0].mux_id); + IPACM_Iface::ipacmcfg->SetQmapId(ext_prop->ext[0].mux_id); + /* sending mux-id info to PCIE-modem for UL */ + if(false == m_filtering.AddOffloadFilteringRule(NULL, ext_prop->ext[0].mux_id, 0)) { - header_partial_default_wan_v4 = true; - } - else + IPACMERR("Failed to send mux id info to modem.\n"); + return IPACM_FAILURE; + } + /* send UL UDP frag filtering rule */ + if(iptype==IPA_IP_v4 && add_offload_frag_rule()) { - header_partial_default_wan_v6 = true; + IPACMERR("Failed to send DL frag rule to modem.\n"); + return IPACM_FAILURE; } - return IPACM_SUCCESS; - } - else - { - if(iptype==IPA_IP_v4) + + /* send ipv6 ICMP filtering rule */ + if(iptype==IPA_IP_v6 && add_icmpv6_exception_rule()) { - header_partial_default_wan_v4 = false; - } - else + IPACMERR("Failed to send ICMPv6 ex rule to modem.\n"); + return IPACM_FAILURE; + } + + /* send ipv4 TCP FIN filtering rule */ + if(iptype==IPA_IP_v4 && add_tcp_fin_rst_exception_rule()) { - header_partial_default_wan_v6 = false; + IPACMERR("Failed to send TCP FIN RST rule to modem.\n"); + return IPACM_FAILURE; } - } - } -#endif + } + else + { + IPACMERR("iface_query is empty.\n"); + return IPACM_FAILURE; + } + } + else + { + IPACM_Wan::backhaul_mode = m_is_sta_mode; + if((iptype==IPA_IP_v4) && (header_set_v4 != true)) + { + header_partial_default_wan_v4 = true; + IPACMDBG_H("STA ipv4-header haven't constructed \n"); + return IPACM_SUCCESS; + } + else if((iptype==IPA_IP_v6) && (header_set_v6 != true)) + { + header_partial_default_wan_v6 = true; + IPACMDBG_H("STA ipv6-header haven't constructed \n"); + return IPACM_SUCCESS; + } + } rt_rule = (struct ipa_ioc_add_rt_rule *) calloc(1, sizeof(struct ipa_ioc_add_rt_rule) + @@ -1424,8 +1915,6 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) rt_rule->num_rules = (uint8_t)NUM; rt_rule->ip = iptype; - - IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name); rt_rule_entry = &rt_rule->rules[0]; rt_rule_entry->at_rear = true; @@ -1453,15 +1942,34 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) rt_rule_entry->rule.hdr_hdl = hdr_hdl_sta_v6; } - if(IPACM_Iface::ipacmcfg->isMCC_Mode == true) + IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name); + /* replace the hdr handle for q6_PCIE*/ + if(m_is_sta_mode == Q6_MHI_WAN) { - IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", - tx_prop->tx[tx_index].alt_dst_pipe); - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + memset(&hdr, 0, sizeof(hdr)); + strlcpy(hdr.name, tx_prop->tx[tx_index].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + free(rt_rule); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; } else { - rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + if(IPACM_Iface::ipacmcfg->isMCC_Mode == true) + { + IPACMDBG_H("In MCC mode, use alt dst pipe: %d\n", + tx_prop->tx[tx_index].alt_dst_pipe); + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].alt_dst_pipe; + } + else + { + rt_rule_entry->rule.dst = tx_prop->tx[tx_index].dst_pipe; + } } memcpy(&rt_rule_entry->rule.attrib, &tx_prop->tx[tx_index].attrib, @@ -1473,10 +1981,21 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) rt_rule_entry->rule.attrib.u.v4.dst_addr = 0; rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0; #ifdef FEATURE_IPA_V3 - rt_rule_entry->rule.hashable = true; #endif - if (false == m_routing.AddRoutingRule(rt_rule)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + if((m_is_sta_mode == WLAN_WAN) && 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_HW); + result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW); + } else { + result = m_routing.AddRoutingRule(rt_rule); + } +#else + result = m_routing.AddRoutingRule(rt_rule); +#endif + if (result == false) { IPACMERR("Routing rule addition failed!\n"); free(rt_rule); @@ -1501,7 +2020,19 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) #ifdef FEATURE_IPA_V3 rt_rule_entry->rule.hashable = true; #endif - if (false == m_routing.AddRoutingRule(rt_rule)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + if((m_is_sta_mode == WLAN_WAN) && 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_HW); + result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + UL_HW); + } else { + result = m_routing.AddRoutingRule(rt_rule); + } +#else + result = m_routing.AddRoutingRule(rt_rule); +#endif + if (result == false) { IPACMERR("Routing rule addition failed!\n"); free(rt_rule); @@ -1518,9 +2049,10 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) /* add a catch-all rule in wan dl routing table */ - if (iptype == IPA_IP_v6) + if (iptype == IPA_IP_v6 && m_is_sta_mode != Q6_MHI_WAN) { strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + IPACMDBG_H(" WAN table created %s \n", rt_rule->rt_tbl_name); memset(rt_rule_entry, 0, sizeof(struct ipa_rt_rule_add)); rt_rule_entry->at_rear = true; if(m_is_sta_mode == Q6_WAN) @@ -1531,6 +2063,7 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) if(m_header.GetHeaderHandle(&hdr) == false) { IPACMERR("Failed to get QMAP header.\n"); + free(rt_rule); return IPACM_FAILURE; } rt_rule_entry->rule.hdr_hdl = hdr.hdl; @@ -1582,6 +2115,7 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } memset(wanup_data, 0, sizeof(ipacm_event_iface_up)); + /* handling filter rule construction */ if (iptype == IPA_IP_v4) { IPACM_Wan::wan_up = true; @@ -1602,34 +2136,33 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname)); wanup_data->ipv4_addr = wan_v4_addr; - if (m_is_sta_mode!=Q6_WAN) - { - wanup_data->is_sta = true; - } - else - { - wanup_data->is_sta = false; - } + wanup_data->backhaul_type = m_is_sta_mode; IPACMDBG_H("Posting IPA_HANDLE_WAN_UP with below information:\n"); IPACMDBG_H("if_name:%s, ipv4_address:0x%x, is sta mode:%d\n", - wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->is_sta); + wanup_data->ifname, wanup_data->ipv4_addr, wanup_data->backhaul_type); memset(&evt_data, 0, sizeof(evt_data)); + /* set backhaul type as xlat */ + IPACM_Wan::is_xlat = is_xlat_local; + /* send xlat configuration for installing uplink rules */ - if(is_xlat && (m_is_sta_mode == Q6_WAN)) + if(is_xlat_local && (m_is_sta_mode == Q6_WAN)) { IPACM_Wan::xlat_mux_id = ext_prop->ext[0].mux_id; wanup_data->xlat_mux_id = IPACM_Wan::xlat_mux_id; IPACMDBG_H("Set xlat configuraiton with below information:\n"); - IPACMDBG_H("xlat_enabled: %d xlat_mux_id: %d \n", - is_xlat, xlat_mux_id); + IPACMDBG_H("xlat_enabled: %d set xlat_mux_id: %d \n", + is_xlat_local, IPACM_Wan::xlat_mux_id); } - else + else /*temp put xlat = 0 for Q6_MHI_WAN*/ { IPACM_Wan::xlat_mux_id = 0; wanup_data->xlat_mux_id = 0; - if(m_is_sta_mode == Q6_WAN) + if(m_is_sta_mode != WLAN_WAN) //both q6_wan/q6_mhi_wan + { wanup_data->mux_id = ext_prop->ext[0].mux_id; + IPACMDBG_H("mux_id: %d\n", wanup_data->mux_id); + } else wanup_data->mux_id = 0; IPACMDBG_H("No xlat configuration\n"); @@ -1664,17 +2197,10 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } memcpy(wanup_data->ifname, dev_name, sizeof(wanup_data->ifname)); - if (m_is_sta_mode!=Q6_WAN) - { - wanup_data->is_sta = true; - } - else - { - wanup_data->is_sta = false; - } + wanup_data->backhaul_type = m_is_sta_mode; memcpy(wanup_data->ipv6_prefix, ipv6_prefix, sizeof(wanup_data->ipv6_prefix)); IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_V6 with below information:\n"); - IPACMDBG_H("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->is_sta); + IPACMDBG_H("if_name:%s, is sta mode: %d\n", wanup_data->ifname, wanup_data->backhaul_type); IPACMDBG_H("ipv6 prefix: 0x%08x%08x.\n", ipv6_prefix[0], ipv6_prefix[1]); memset(&evt_data, 0, sizeof(evt_data)); evt_data.event = IPA_HANDLE_WAN_UP_V6; @@ -1685,20 +2211,22 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) post_wan_up_tether_evt(IPA_IP_v6, 0); #endif } - if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0) - { + + if(IPACM_Iface::ipacmcfg->GetIPAVer() >= IPA_HW_None && IPACM_Iface::ipacmcfg->GetIPAVer() < IPA_HW_v4_0) + { /* Add corresponding ipa_rm_resource_name of TX-endpoint up before IPV6 RT-rule set */ IPACMDBG_H("dev %s add 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->AddRmDepend(IPACM_Iface::ipacmcfg->ipa_client_rm_map_tbl[tx_prop->tx[0].dst_pipe],false); #ifdef WAN_IOC_NOTIFY_WAN_STATE - } else { - if (m_is_sta_mode == Q6_WAN && ipa_pm_q6_check == 0) + } else { + if ((m_is_sta_mode == Q6_WAN && ipa_pm_q6_check == 0 ) || (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); + free(rt_rule); return false; } IPACMDBG_H("send WAN_IOC_NOTIFY_WAN_STATE up to IPA_PM\n"); @@ -1711,10 +2239,9 @@ int IPACM_Wan::handle_route_add_evt(ipa_ip_type iptype) } ipa_pm_q6_check++; IPACMDBG_H("update ipa_pm_q6_check to %d\n", ipa_pm_q6_check); - - } + } #else -} + } #endif if(rt_rule != NULL) { @@ -1739,22 +2266,16 @@ int IPACM_Wan::post_wan_up_tether_evt(ipa_ip_type iptype, int ipa_if_num_tether) memset(wanup_data, 0, sizeof(ipacm_event_iface_up_tehter)); wanup_data->if_index_tether = ipa_if_num_tether; - if (m_is_sta_mode!=Q6_WAN) - { - wanup_data->is_sta = true; - } - else - { - wanup_data->is_sta = false; - } + wanup_data->backhaul_type = m_is_sta_mode; /* xlat mux-id*/ - if(is_xlat && (m_is_sta_mode == Q6_WAN)) + if(is_xlat_local && (m_is_sta_mode == Q6_WAN)) wanup_data->xlat_mux_id = ext_prop->ext[0].mux_id; else wanup_data->xlat_mux_id = 0; IPACMDBG_H("Posting IPA_HANDLE_WAN_UP_TETHER with below information:\n"); IPACMDBG_H("tether_if_name:%s, is sta mode:%d xlat_mux_id: %d\n", - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wanup_data->is_sta, wanup_data->xlat_mux_id); + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wanup_data->backhaul_type, wanup_data->xlat_mux_id); + memset(&evt_data, 0, sizeof(evt_data)); if (iptype == IPA_IP_v4) @@ -1806,17 +2327,10 @@ int IPACM_Wan::post_wan_down_tether_evt(ipa_ip_type iptype, int ipa_if_num_tethe memset(wandown_data, 0, sizeof(ipacm_event_iface_up_tehter)); wandown_data->if_index_tether = ipa_if_num_tether; - if (m_is_sta_mode!=Q6_WAN) - { - wandown_data->is_sta = true; - } - else - { - wandown_data->is_sta = false; - } + wandown_data->backhaul_type = m_is_sta_mode; IPACMDBG_H("Posting IPA_HANDLE_WAN_DOWN_TETHER with below information:\n"); IPACMDBG_H("tether_if_name:%s, is sta mode:%d\n", - IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wandown_data->is_sta); + IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether].iface_name, wandown_data->backhaul_type); memset(&evt_data, 0, sizeof(evt_data)); if (iptype == IPA_IP_v4) @@ -2000,6 +2514,7 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) { struct ipa_flt_rule_add flt_rule_entry; int i, rule_v4 = 0, rule_v6 = 0, len; + bool result; IPACMDBG_H("ip-family: %d; \n", iptype); @@ -2013,29 +2528,35 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) memset(&firewall_config, 0, sizeof(firewall_config)); strlcpy(firewall_config.firewall_config_file, "/etc/mobileap_firewall.xml", sizeof(firewall_config.firewall_config_file)); - IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); - if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) + if(m_is_sta_mode != Q6_MHI_WAN) { - IPACMDBG_H("QCMAP Firewall XML read OK \n"); - /* find the number of v4/v6 firewall rules */ - for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) + IPACMDBG_H("Firewall XML file is %s \n", firewall_config.firewall_config_file); + if (IPACM_SUCCESS == IPACM_read_firewall_xml(firewall_config.firewall_config_file, &firewall_config)) { - if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) - { - rule_v4++; - } - else + IPACMDBG_H("QCMAP Firewall XML read OK \n"); + /* find the number of v4/v6 firewall rules */ + for (i = 0; i < firewall_config.num_extd_firewall_entries; i++) { - rule_v6++; + if (firewall_config.extd_firewall_entries[i].ip_vsn == 4) + { + rule_v4++; + } + else + { + rule_v6++; + } } + IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries); + } + else + { + IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); } - IPACMDBG_H("firewall rule v4:%d v6:%d total:%d\n", rule_v4, rule_v6, firewall_config.num_extd_firewall_entries); } else { - IPACMERR("QCMAP Firewall XML read failed, no that file, use default configuration \n"); + IPACMDBG_H("in Q6_MHI_WAN mode, skip firewall, use default configuration \n"); } - /* construct ipa_ioc_add_flt_rule with N firewall rules */ ipa_ioc_add_flt_rule *m_pFilteringTable = NULL; len = sizeof(struct ipa_ioc_add_flt_rule) + 1 * sizeof(struct ipa_flt_rule_add); @@ -2068,7 +2589,19 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) memcpy(&flt_rule_entry.rule.attrib, &rx_prop->rx[0].attrib, sizeof(struct ipa_rule_attrib)); flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_FRAGMENT; memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + if (false == result) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -2153,9 +2686,27 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x00000000; flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x00000000; - memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + /* disble meta-data filtering */ + if(m_is_sta_mode == Q6_MHI_WAN) + { + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + IPACMDBG_H("disable meta-data filtering 0x%x\n", flt_rule_entry.rule.attrib.attrib_mask); + } - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + if (false == result) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -2242,7 +2793,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) IPACMDBG_H("Filter rule attrib mask: 0x%x\n", m_pFilteringTable->rules[0].rule.attrib.attrib_mask); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (false == result) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -2266,7 +2830,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) IPACMDBG_H("Filter rule attrib mask: 0x%x\n", m_pFilteringTable->rules[0].rule.attrib.attrib_mask); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (false == result) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -2290,7 +2867,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) IPACMDBG_H("Filter rule attrib mask: 0x%x\n", m_pFilteringTable->rules[0].rule.attrib.attrib_mask); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (false == result) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -2366,7 +2956,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) IPACMDBG_H("Filter rule attrib mask: 0x%x\n", m_pFilteringTable->rules[0].rule.attrib.attrib_mask); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (false == result) { IPACMERR("Error Adding RuleTable(0) to Filtering, aborting...\n"); free(m_pFilteringTable); @@ -2395,40 +2998,57 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) m_pFilteringTable->ip = IPA_IP_v6; m_pFilteringTable->num_rules = (uint8_t)1; - /* Construct ICMP rule */ - 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.eq_attrib_type = 0; - flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + if(m_is_sta_mode != Q6_MHI_WAN) + { + /* Construct ICMP rule */ + 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.eq_attrib_type = 0; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; #ifdef FEATURE_IPA_V3 flt_rule_entry.rule.hashable = true; #endif - memcpy(&flt_rule_entry.rule.attrib, - &rx_prop->rx[0].attrib, - sizeof(struct ipa_rule_attrib)); - flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; - flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; - memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + memcpy(&flt_rule_entry.rule.attrib, + &rx_prop->rx[0].attrib, + sizeof(struct ipa_rule_attrib)); + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) - { - IPACMERR("Error Adding Filtering rules, aborting...\n"); - free(m_pFilteringTable); - return IPACM_FAILURE; + if (false == result) + { + IPACMERR("Error Adding Filtering rules, aborting...\n"); + free(m_pFilteringTable); + return IPACM_FAILURE; + } + else + { + IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + } + /* copy filter hdls */ + dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl; + /* End of construct ICMP rule */ } else { - IPACM_Iface::ipacmcfg->increaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); - IPACMDBG_H("flt rule hdl0=0x%x, status=0x%x\n", m_pFilteringTable->rules[0].flt_rule_hdl, m_pFilteringTable->rules[0].status); + IPACMDBG_H("in Q6_MHI_WAN mode, skip ICMPv6 flt rule \n"); } - /* copy filter hdls */ - dft_wan_fl_hdl[2] = m_pFilteringTable->rules[0].flt_rule_hdl; - - /* End of construct ICMP rule */ - /* v6 default route */ memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); if (false == m_routing.GetRoutingTable(&IPACM_Iface::ipacmcfg->rt_tbl_wan_v6)) //rt_tbl_wan_v6 rt_tbl_v6 @@ -2443,25 +3063,24 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.rt_tbl_hdl = IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.hdl; /* firewall disable, all traffic are allowed */ - if(firewall_config.firewall_enable == true) + if(firewall_config.firewall_enable == true) { - flt_rule_entry.at_rear = true; - - /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ - if(firewall_config.rule_action_accept == true) - { - flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; - } - else - { + flt_rule_entry.at_rear = true; + /* default action for v6 is PASS_TO_ROUTE unless user set to exception*/ + if(firewall_config.rule_action_accept == true) + { + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + } + else + { flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - } - } + } + } else { flt_rule_entry.at_rear = true; flt_rule_entry.rule.action = IPA_PASS_TO_ROUTING; - } + } #ifdef FEATURE_IPA_V3 flt_rule_entry.rule.hashable = true; #endif @@ -2477,10 +3096,28 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000; flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000; + /* disble meta-data filtering */ + if(m_is_sta_mode == Q6_MHI_WAN) + { + flt_rule_entry.rule.attrib.attrib_mask &= ~((uint32_t)IPA_FLT_META_DATA); + IPACMDBG_H("disable meta-data filtering 0x%x\n", flt_rule_entry.rule.attrib.attrib_mask); + } memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + if (false == result) { IPACMERR("Error Adding Filtering rules, aborting...\n"); free(m_pFilteringTable); @@ -2551,7 +3188,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) /* insert TCP rule*/ flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_TCP; memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (false == result) { IPACMERR("Error Adding Filtering rules, aborting...\n"); free(m_pFilteringTable); @@ -2570,7 +3220,19 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) /* insert UDP rule*/ flt_rule_entry.rule.attrib.u.v6.next_hdr = IPACM_FIREWALL_IPPROTO_UDP; memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + if (false == result) { IPACMERR("Error Adding Filtering rules, aborting...\n"); free(m_pFilteringTable); @@ -2589,7 +3251,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) else { memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) + +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + if (false == result) { IPACMERR("Error Adding Filtering rules, aborting...\n"); free(m_pFilteringTable); @@ -2627,7 +3302,19 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + if (result == false) { IPACMERR("Error Adding Filtering rules, aborting...\n"); free(m_pFilteringTable); @@ -2687,7 +3374,20 @@ int IPACM_Wan::config_dft_firewall_rules(ipa_ip_type iptype) memcpy(&(m_pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); - if (false == m_filtering.AddFilteringRule(m_pFilteringTable)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_ALL); + result = m_filtering.AddFilteringRule_hw_index(m_pFilteringTable, IPACM_Iface::ipacmcfg->hw_counter_offset+ DL_ALL); + } else { + result = m_filtering.AddFilteringRule(m_pFilteringTable); + } +#else + result = m_filtering.AddFilteringRule(m_pFilteringTable); +#endif + + if (result == false) { IPACMERR("Error Adding Filtering rules, aborting...\n"); free(m_pFilteringTable); @@ -3991,7 +4691,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) if (num_firewall_v4 != 0) { if (m_filtering.DeleteFilteringHdls(firewall_hdl_v4, - IPA_IP_v4, num_firewall_v4) == false) + IPA_IP_v4, num_firewall_v4) == false) { IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; @@ -4004,7 +4704,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) } if (m_filtering.DeleteFilteringHdls(dft_wan_fl_hdl, - IPA_IP_v4, 1) == false) + IPA_IP_v4, 1) == false) { IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; @@ -4025,7 +4725,7 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) if (num_firewall_v6 != 0) { if (m_filtering.DeleteFilteringHdls(firewall_hdl_v6, - IPA_IP_v6, num_firewall_v6) == false) + IPA_IP_v6, num_firewall_v6) == false) { IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; @@ -4038,20 +4738,27 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) } if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[1], - IPA_IP_v6, 1) == false) + IPA_IP_v6, 1) == false) { IPACMERR("Error Deleting Filtering rules, aborting...\n"); return IPACM_FAILURE; } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); - if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2], - IPA_IP_v6, 1) == false) + + if(m_is_sta_mode != Q6_MHI_WAN) { - IPACMERR("Error Deleting Filtering rules, aborting...\n"); - return IPACM_FAILURE; + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + if (m_filtering.DeleteFilteringHdls(&dft_wan_fl_hdl[2], + IPA_IP_v6, 1) == false) + { + IPACMERR("Error Deleting Filtering rules, aborting...\n"); + return IPACM_FAILURE; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); + } + else + { + IPACMDBG_H("in Q6_MHI_WAN mode, skip ICMPv6 flt rule deletion\n"); } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, 1); - if (is_ipv6_frag_firewall_flt_rule_installed && check_dft_firewall_rules_attr_mask(&firewall_config)) { @@ -4065,7 +4772,6 @@ int IPACM_Wan::del_dft_firewall_rules(ipa_ip_type iptype) } num_firewall_v6 = 0; } - return IPACM_SUCCESS; } @@ -4074,6 +4780,11 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) { uint32_t tx_index; ipacm_cmd_q_data evt_data; +#ifdef WAN_IOC_NOTIFY_WAN_STATE + struct wan_ioctl_notify_wan_state wan_state; + int fd_wwan_ioctl; + memset(&wan_state, 0, sizeof(wan_state)); +#endif IPACMDBG_H("got handle_route_del_evt for STA-mode with ip-family:%d \n", iptype); @@ -4096,6 +4807,33 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) 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 + { + /* 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 + } + for (tx_index = 0; tx_index < iface_query->num_tx_props; tx_index++) { if(iptype != tx_prop->tx[tx_index].ip) @@ -4128,7 +4866,7 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) } /* Delete the default wan route*/ - if (iptype == IPA_IP_v6) + if (iptype == IPA_IP_v6 && m_is_sta_mode != Q6_MHI_WAN) { IPACMDBG_H("ip-type %d: default v6 wan RT-rule deleted\n",iptype); if (m_routing.DeleteRoutingHdl(wan_route_rule_v6_hdl_a5[0], IPA_IP_v6) == false) @@ -4149,14 +4887,7 @@ int IPACM_Wan::handle_route_del_evt(ipa_ip_type iptype) if (iptype == IPA_IP_v4) { wandown_data->ipv4_addr = wan_v4_addr; - if (m_is_sta_mode!=Q6_WAN) - { - wandown_data->is_sta = true; - } - else - { - wandown_data->is_sta = false; - } + wandown_data->backhaul_type = m_is_sta_mode; evt_data.event = IPA_HANDLE_WAN_DOWN; evt_data.evt_data = (void *)wandown_data; /* Insert IPA_HANDLE_WAN_DOWN to command queue */ @@ -4178,17 +4909,30 @@ 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)); } - } - else - { - if (m_is_sta_mode!=Q6_WAN) + + /* Delete MHI frag rule */ + 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()) { - wandown_data->is_sta = true; + IPACMERR("Failed to delete icmpv6 rule \n"); + return IPACM_FAILURE; } - else + /* Delete tcp_fin_rst rule */ + if(delete_tcp_fin_rst_exception_rule()) { - wandown_data->is_sta = false; + IPACMERR("Failed to delete tcp_fin_rst rule \n"); + return IPACM_FAILURE; } + } + 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; evt_data.evt_data = (void *)wandown_data; @@ -4294,14 +5038,7 @@ int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype) if (iptype == IPA_IP_v4) { wandown_data->ipv4_addr = wan_v4_addr; - if (m_is_sta_mode!=Q6_WAN) - { - wandown_data->is_sta = true; - } - else - { - wandown_data->is_sta = false; - } + wandown_data->backhaul_type = m_is_sta_mode; evt_data.event = IPA_HANDLE_WAN_DOWN; evt_data.evt_data = (void *)wandown_data; /* Insert IPA_HANDLE_WAN_DOWN to command queue */ @@ -4322,14 +5059,8 @@ int IPACM_Wan::handle_route_del_evt_ex(ipa_ip_type iptype) } else { - if (m_is_sta_mode!=Q6_WAN) - { - wandown_data->is_sta = true; - } - else - { - wandown_data->is_sta = false; - } + + 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; evt_data.evt_data = (void *)wandown_data; @@ -4522,6 +5253,18 @@ 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 */ #ifdef FEATURE_IPACM_HAL @@ -4551,6 +5294,19 @@ 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 @@ -4572,26 +5328,14 @@ int IPACM_Wan::handle_down_evt() #endif } - /* Delete default v4 RT rule */ - if (ip_type != IPA_IP_v6) - { - 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) + 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++) + /* Delete default v4 RT rule */ + if (ip_type != IPA_IP_v6) { - if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + /* 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; @@ -4599,130 +5343,143 @@ int IPACM_Wan::handle_down_evt() } } - IPACMDBG_H("finished delete default v6 RT rules\n "); - } - - - /* 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++) - { - /* Del NAT rules before ipv4 RT rules are delete */ - if(get_client_memptr(wan_client, i)->ipv4_set == true) + /* 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++) { - IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr); - CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr); + 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 "); + } + /* 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++) + { + /* Del NAT rules before ipv4 RT rules are delete */ + if(get_client_memptr(wan_client, i)->ipv4_set == true) + { + IPACMDBG_H("Clean Nat Rules for ipv4:0x%x\n", get_client_memptr(wan_client, i)->v4_addr); + CtList->HandleSTAClientDelEvt(get_client_memptr(wan_client, i)->v4_addr); + } - if (delete_wan_rtrules(i, IPA_IP_v4)) + if (delete_wan_rtrules(i, IPA_IP_v4)) + { + IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + if (delete_wan_rtrules(i, IPA_IP_v6)) + { + IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i); + res = IPACM_FAILURE; + goto fail; + } + + IPACMDBG_H("Delete %d client header\n", num_wan_client); + if(get_client_memptr(wan_client, i)->ipv4_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + if(get_client_memptr(wan_client, i)->ipv6_header_set == true) + { + if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6) + == false) + { + res = IPACM_FAILURE; + goto fail; + } + } + } /* end of for loop */ + /* 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) { - IPACMERR("unbale to delete wan-client v4 route rules for index %d\n", i); - res = IPACM_FAILURE; - goto fail; + handle_software_routing_disable(true); } - - if (delete_wan_rtrules(i, IPA_IP_v6)) + else { - IPACMERR("unbale to delete ecm-client v6 route rules for index %d\n", i); - res = IPACM_FAILURE; - goto fail; + handle_software_routing_disable(false); } - - IPACMDBG_H("Delete %d client header\n", num_wan_client); - - - if(get_client_memptr(wan_client, i)->ipv4_header_set == true) + } + /* free dft ipv4 filter rule handlers if any */ + if (ip_type != IPA_IP_v6 && rx_prop != NULL) + { + if (dft_v4fl_rule_hdl[0] != 0) { - if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v4) - == false) + if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, + IPA_IP_v4, + IPV4_DEFAULT_FILTERTING_RULES) == false) { + IPACMERR("Error Delete Filtering rules, aborting...\n"); res = IPACM_FAILURE; goto fail; } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); + IPACMDBG_H("finished delete default v4 filtering rules\n "); } - - if(get_client_memptr(wan_client, i)->ipv6_header_set == true) - { - if (m_header.DeleteHeaderHdl(get_client_memptr(wan_client, i)->hdr_hdl_v6) - == false) + } + /* free dft ipv6 filter rule handlers if any */ + if (ip_type != IPA_IP_v4 && rx_prop != NULL) + { + if (dft_v6fl_rule_hdl[0] != 0) { - res = IPACM_FAILURE; - goto fail; - } + if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, + IPA_IP_v6, + IPV6_DEFAULT_FILTERTING_RULES) == false) + { + IPACMERR("ErrorDeleting Filtering rule, aborting...\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); } - } /* end of for loop */ - - /* free the edm clients cache */ - IPACMDBG_H("Free wan clients cache\n"); - - /* check software routing fl rule hdl */ - if (softwarerouting_act == true) - { - handle_software_routing_disable(); - } - - /* free dft ipv4 filter rule handlers if any */ - if (ip_type != IPA_IP_v6 && rx_prop != NULL) - { - if (dft_v4fl_rule_hdl[0] != 0) - { - if (m_filtering.DeleteFilteringHdls(dft_v4fl_rule_hdl, - IPA_IP_v4, - IPV4_DEFAULT_FILTERTING_RULES) == false) + if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES) { - IPACMERR("Error Delete Filtering rules, aborting...\n"); - res = IPACM_FAILURE; - goto fail; + if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl, IPA_IP_v6, num_ipv6_dest_flt_rule) == false) + { + IPACMERR("Failed to delete ipv6 dest flt rules.\n"); + res = IPACM_FAILURE; + goto fail; + } + IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_ipv6_dest_flt_rule); } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v4, IPV4_DEFAULT_FILTERTING_RULES); - IPACMDBG_H("finished delete default v4 filtering rules\n "); + IPACMDBG_H("finished delete default v6 filtering rules\n "); } - } - - /* free dft ipv6 filter rule handlers if any */ - if (ip_type != IPA_IP_v4 && rx_prop != NULL) - { - if (dft_v6fl_rule_hdl[0] != 0) + if(hdr_proc_hdl_dummy_v6) { - if (m_filtering.DeleteFilteringHdls(dft_v6fl_rule_hdl, - IPA_IP_v6, - IPV6_DEFAULT_FILTERTING_RULES) == false) + if(m_header.DeleteHeaderProcCtx(hdr_proc_hdl_dummy_v6) == false) { - IPACMERR("ErrorDeleting Filtering rule, aborting...\n"); + IPACMERR("Failed to delete hdr_proc_hdl_dummy_v6\n"); res = IPACM_FAILURE; goto fail; } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, IPV6_DEFAULT_FILTERTING_RULES); } - - if(num_ipv6_dest_flt_rule > 0 && num_ipv6_dest_flt_rule <= MAX_DEFAULT_v6_ROUTE_RULES) + if(hdr_hdl_dummy_v6) { - if(m_filtering.DeleteFilteringHdls(ipv6_dest_flt_rule_hdl, IPA_IP_v6, num_ipv6_dest_flt_rule) == false) + if (m_header.DeleteHeaderHdl(hdr_hdl_dummy_v6) == false) { - IPACMERR("Failed to delete ipv6 dest flt rules.\n"); + IPACMERR("Failed to delete hdr_hdl_dummy_v6\n"); res = IPACM_FAILURE; goto fail; } - IPACM_Iface::ipacmcfg->decreaseFltRuleCount(rx_prop->rx[0].src_pipe, IPA_IP_v6, num_ipv6_dest_flt_rule); - } - IPACMDBG_H("finished delete default v6 filtering rules\n "); - } - if(hdr_proc_hdl_dummy_v6) - { - if(m_header.DeleteHeaderProcCtx(hdr_proc_hdl_dummy_v6) == false) - { - IPACMERR("Failed to delete hdr_proc_hdl_dummy_v6\n"); - res = IPACM_FAILURE; - goto fail; - } - } - if(hdr_hdl_dummy_v6) - { - if (m_header.DeleteHeaderHdl(hdr_hdl_dummy_v6) == false) - { - IPACMERR("Failed to delete hdr_hdl_dummy_v6\n"); - res = IPACM_FAILURE; - goto fail; } } fail: @@ -4845,6 +5602,21 @@ int IPACM_Wan::handle_down_evt_ex() install_wan_filtering_rule(false); } + IPACMDBG_H("Delete default v4 coalesce routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule RSC TCP deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false) + { + IPACMERR("Routing rule RSB UDP deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) { IPACMERR("Routing rule deletion failed!\n"); @@ -4903,6 +5675,13 @@ int IPACM_Wan::handle_down_evt_ex() for (i = 0; i < 2*num_dft_rt_v6; i++) { + /* delete v6 colasce rules */ + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Colasce Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) { IPACMERR("Routing rule deletion failed!\n"); @@ -4987,6 +5766,21 @@ int IPACM_Wan::handle_down_evt_ex() install_wan_filtering_rule(false); } + IPACMDBG_H("Delete default v4 coalesce routing rules\n"); + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing rule RSC TCP deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false) + { + IPACMERR("Routing rule RSB UDP deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[0], IPA_IP_v4) == false) { IPACMERR("Routing rule deletion failed!\n"); @@ -4996,6 +5790,13 @@ int IPACM_Wan::handle_down_evt_ex() for (i = 0; i < 2*num_dft_rt_v6; i++) { + /* delete v6 colasce rules */ + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Colasce Routing rule deletion failed!\n"); + res = IPACM_FAILURE; + goto fail; + } if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) { IPACMERR("Routing rule deletion failed!\n"); @@ -5005,11 +5806,11 @@ int IPACM_Wan::handle_down_evt_ex() } } - /* check software routing fl rule hdl */ - if (softwarerouting_act == true) - { - handle_software_routing_disable(); - } +// /* check software routing fl rule hdl */ +// if (softwarerouting_act == true) +// { +// handle_software_routing_disable(); +// } fail: if (tx_prop != NULL) @@ -5316,57 +6117,6 @@ fail: return res; } -void IPACM_Wan::change_to_network_order(ipa_ip_type iptype, ipa_rule_attrib* attrib) -{ - if(attrib == NULL) - { - IPACMERR("Attribute pointer is NULL.\n"); - return; - } - - if(iptype == IPA_IP_v6) - { - int i; - for(i=0; i<4; i++) - { - attrib->u.v6.src_addr[i] = htonl(attrib->u.v6.src_addr[i]); - attrib->u.v6.src_addr_mask[i] = htonl(attrib->u.v6.src_addr_mask[i]); - attrib->u.v6.dst_addr[i] = htonl(attrib->u.v6.dst_addr[i]); - attrib->u.v6.dst_addr_mask[i] = htonl(attrib->u.v6.dst_addr_mask[i]); - } - } - else - { - IPACMDBG_H("IP type is not IPv6, do nothing: %d\n", iptype); - } - - return; -} - -bool IPACM_Wan::is_global_ipv6_addr(uint32_t* ipv6_addr) -{ - if(ipv6_addr == NULL) - { - IPACMERR("IPv6 address is empty.\n"); - return false; - } - IPACMDBG_H("Get ipv6 address with first word 0x%08x.\n", ipv6_addr[0]); - - uint32_t ipv6_link_local_prefix, ipv6_link_local_prefix_mask; - ipv6_link_local_prefix = 0xFE800000; - ipv6_link_local_prefix_mask = 0xFFC00000; - if((ipv6_addr[0] & ipv6_link_local_prefix_mask) == (ipv6_link_local_prefix & ipv6_link_local_prefix_mask)) - { - IPACMDBG_H("This IPv6 address is link local.\n"); - return false; - } - else - { - IPACMDBG_H("This IPv6 address is not link local.\n"); - return true; - } -} - /* handle STA WAN-client */ /* handle WAN client initial, construct full headers (tx property) */ int IPACM_Wan::handle_wan_hdr_init(uint8_t *mac_addr) @@ -6430,3 +7180,736 @@ int IPACM_Wan::add_dummy_rx_hdr() } return IPACM_SUCCESS; } + +int IPACM_Wan::handle_coalesce_evt() +{ + struct ipa_ioc_add_rt_rule *rt_rule = NULL; + struct ipa_rt_rule_add *rt_rule_entry; + const int NUM_RULES = 1; + int res = IPACM_SUCCESS; + struct ipa_ioc_get_hdr hdr; + uint32_t i; + + if(wan_v4_addr_set) + { + /* Delete default RSC v4 RT rule */ + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[0], IPA_IP_v4) == false) + { + IPACMERR("Routing old RSC TCP RT rule deletion failed!\n"); + return IPACM_FAILURE; + } + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[1], IPA_IP_v4) == false) + { + IPACMERR("Routing old RSB UDP RT rule deletion failed!\n"); + return IPACM_FAILURE; + } + /* 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 old RT rule deletion failed!\n"); + return IPACM_FAILURE; + } + + /* apply the new coalesce configuration */ + 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)); + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v4; + rt_rule_entry = &rt_rule->rules[0]; + rt_rule_entry->at_rear = false; + rt_rule_entry->rule.attrib.attrib_mask = IPA_FLT_DST_ADDR; + /* still need setup v4 default routing rule to APPs*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name, sizeof(rt_rule->rt_tbl_name)); + rt_rule_entry->rule.attrib.u.v4.dst_addr = wan_v4_addr; + rt_rule_entry->rule.attrib.u.v4.dst_addr_mask = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif + /* query qmap header*/ + memset(&hdr, 0, sizeof(hdr)); + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + res = IPACM_FAILURE; + goto fail; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + /* default v4 rt-rule */ +#ifdef IPA_RT_SUPPORT_COAL + rt_rule_entry->rule.coalesce = false; +#endif + /* default v4 rt-rule */ + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rt-rule hdll=0x%x\n", dft_rt_rule_hdl[0]); + + /* RSC TCP rule*/ + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_PROTOCOL; + rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_coalesce_rt_rule_hdl[0] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[0], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable); + + /* RSB UDP rule*/ + rt_rule_entry->rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail; + } + else if (rt_rule_entry->status) + { + IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail; + } + dft_coalesce_rt_rule_hdl[1] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv4 wan iface rsb udp rt-rule hdll=0x%x enable(%d)\n", dft_coalesce_rt_rule_hdl[1], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable); +fail: + free(rt_rule); + } + /* v6 */ + if (num_dft_rt_v6 !=0) + { + for (i = 0; i < 2*num_dft_rt_v6; i++) + { + /* delete v6 colasce rules */ + if (m_routing.DeleteRoutingHdl(dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Colasce Routing rule deletion failed!\n"); + return IPACM_FAILURE; + } + /* delete v6 default rules */ + if (m_routing.DeleteRoutingHdl(dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES+i], IPA_IP_v6) == false) + { + IPACMERR("Routing rule deletion failed!\n"); + return IPACM_FAILURE; + } + } + + 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)); + if (!rt_rule) + { + IPACMERR("Error Locate ipa_ioc_add_rt_rule memory...\n"); + return IPACM_FAILURE; + } + rt_rule->commit = 1; + rt_rule->num_rules = NUM_RULES; + rt_rule->ip = IPA_IP_v6; + + for (i = 0; i < num_dft_rt_v6; i++) + { + /* setup same rule for v6_wan table */ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_v6.name, sizeof(rt_rule->rt_tbl_name)); + 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_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; + rt_rule_entry->rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; +#ifdef FEATURE_IPA_V3 + rt_rule_entry->rule.hashable = false; +#endif + strlcpy(hdr.name, tx_prop->tx[0].hdr_name, sizeof(hdr.name)); + hdr.name[IPA_RESOURCE_NAME_MAX-1] = '\0'; + if(m_header.GetHeaderHandle(&hdr) == false) + { + IPACMERR("Failed to get QMAP header.\n"); + return IPACM_FAILURE; + } + rt_rule_entry->rule.hdr_hdl = hdr.hdl; + rt_rule_entry->rule.dst = IPA_CLIENT_APPS_WAN_CONS; + /* legacy default v4 rt-rule */ +#ifdef IPA_RT_SUPPORT_COAL + rt_rule_entry->rule.coalesce = false; +#endif + /* legacy default v6 rt-rule */ + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail2; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail2; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i] = rt_rule_entry->rt_rule_hdl; + + /* setup same rule for v6_lan table*/ + strlcpy(rt_rule->rt_tbl_name, IPACM_Iface::ipacmcfg->rt_tbl_wan_v6.name, sizeof(rt_rule->rt_tbl_name)); + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail2; + } + else if (rt_rule_entry->status) + { + IPACMERR("rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail2; + } + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv6 wan iface rt-rule hdl=0x%x hdl=0x%x, entry: %d %d\n", + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i], + dft_rt_rule_hdl[MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1], + MAX_DEFAULT_v4_ROUTE_RULES + 2*i, + MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1); + /* RSC TCP rule*/ + rt_rule_entry->rule.attrib.attrib_mask |= IPA_FLT_NEXT_HDR; + rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail2; + } + else if (rt_rule_entry->status) + { + IPACMERR("rsc tcp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail2; + } + dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv6 wan iface rsc tcp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_tcp_enable); + /* RSB UDP rule*/ + rt_rule_entry->rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_UDP; +#ifdef IPA_RT_SUPPORT_COAL + if (IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable) + rt_rule_entry->rule.coalesce = true; + else + rt_rule_entry->rule.coalesce = false; +#endif + if (false == m_routing.AddRoutingRule(rt_rule)) + { + IPACMERR("Routing rule addition failed!\n"); + res = IPACM_FAILURE; + goto fail2; + } + else if (rt_rule_entry->status) + { + IPACMERR("rsb udp rt rule adding failed. Result=%d\n", rt_rule_entry->status); + res = rt_rule_entry->status; + goto fail2; + } + dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1] = rt_rule_entry->rt_rule_hdl; + IPACMDBG_H("ipv6 wan iface rsb udp rt-rule hdll=0x%x\n enable(%d)", dft_coalesce_rt_rule_hdl[2*MAX_DEFAULT_v4_ROUTE_RULES + 2*i+1], + IPACM_Wan::coalesce_enable_info[ext_prop->ext[0].mux_id].coalesce_udp_enable); + } +fail2: + free(rt_rule); + } + return res; +} + +int IPACM_Wan::add_offload_frag_rule() +{ + int fd; + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable = NULL; + + mux_id = ext_prop->ext[0].mux_id; + /* contruct filter rules to pcie modem */ + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_generate_flt_eq flt_eq; + + /* construct rule */ + IPACMDBG_H("adding MHi frag rule\n"); + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->global = false; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_rules = (uint8_t)1; + + /* Configuring Fragment Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.at_rear = false; + 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_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + 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_FRAGMENT; + + /* generate eq */ + 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_v4; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + free(pFilteringTable); + return IPACM_FAILURE; + } + + if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct + { + IPACMERR("Failed to get eq_attrib\n"); + goto fail; + } + memcpy(&flt_rule_entry.rule.eq_attrib, + &flt_eq.eq_attrib, + sizeof(flt_rule_entry.rule.eq_attrib)); + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add rule */ + if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 1)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + + /* save handle */ + mhi_dl_v4_frag_hdl = pFilteringTable->rules[0].flt_rule_hdl; + +fail: + close(fd); + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Wan::delete_offload_frag_rule() +{ + int res = IPACM_SUCCESS; + int len; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + + struct ipa_flt_rule_del flt_rule_entry; + + IPACMDBG_H("deleting MHI frag rule \n"); + len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return false; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_hdls = (uint8_t)1; + + if (mhi_dl_v4_frag_hdl == 0) + { + IPACMERR("invalid dl_v4_frag_hdl.\n"); + res = false; + goto fail; + } + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = mhi_dl_v4_frag_hdl; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to delete DL offload frag rule.\n"); + res = false; + goto fail; + } + mhi_dl_v4_frag_hdl = 0; + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Wan::add_icmpv6_exception_rule() +{ + int fd; + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable = NULL; + + mux_id = ext_prop->ext[0].mux_id; + /* contruct filter rules to pcie modem */ + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_generate_flt_eq flt_eq; + + /* construct rule */ + IPACMDBG_H("adding MHI icmpv6 rule\n"); + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->global = false; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_rules = (uint8_t)1; + + /* Configuring ICMPv6 Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = false; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + 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_NEXT_HDR; + flt_rule_entry.rule.attrib.u.v6.next_hdr = (uint8_t)IPACM_FIREWALL_IPPROTO_ICMP6; + + /* generate eq */ + 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; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + free(pFilteringTable); + return IPACM_FAILURE; + } + + if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct + { + 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)); + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add rule */ + if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 1)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + + /* save handle */ + icmpv6_exception_hdl = pFilteringTable->rules[0].flt_rule_hdl; + +fail: + close(fd); + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Wan::delete_icmpv6_exception_rule() +{ + int len, res = IPACM_SUCCESS; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + + struct ipa_flt_rule_del flt_rule_entry; + + IPACMDBG_H("deleting MHI icmpv6 rule \n"); + len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_hdls = (uint8_t)1; + + if (icmpv6_exception_hdl == 0) + { + IPACMERR("invalid icmpv6_exception_hdl.\n"); + res = IPACM_FAILURE; + goto fail; + } + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = icmpv6_exception_hdl; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to delete MHI icmpv6 rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + icmpv6_exception_hdl = 0; + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Wan::add_tcp_fin_rst_exception_rule() +{ + int fd; + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable = NULL; + + mux_id = ext_prop->ext[0].mux_id; + /* contruct filter rules to pcie modem */ + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_generate_flt_eq flt_eq; + + /* construct rule */ + IPACMDBG_H("adding MHI TCP FIN RST rule\n"); + len = sizeof(struct ipa_ioc_add_flt_rule) + (2 * sizeof(struct ipa_flt_rule_add)); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->global = false; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_rules = (uint8_t)2; + + /* Configuring TCP FIN RST Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_add)); + flt_rule_entry.rule.retain_hdr = 1; + flt_rule_entry.rule.to_uc = 0; + flt_rule_entry.rule.eq_attrib_type = 0; + flt_rule_entry.at_rear = false; + flt_rule_entry.flt_rule_hdl = -1; + flt_rule_entry.status = -1; + flt_rule_entry.rule.action = IPA_PASS_TO_EXCEPTION; + /* + * need this since fin is last packet in an ongoing TCP connection + * so it will always match the previous hash and take MHIP path + */ + flt_rule_entry.rule.hashable = false; + + IPACMDBG_H("rx property attrib mask:0x%x\n", rx_prop->rx[0].attrib.attrib_mask); + 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_PROTOCOL; + flt_rule_entry.rule.attrib.u.v4.protocol = (uint8_t)IPACM_FIREWALL_IPPROTO_TCP; + + /* generate eq */ + 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_v4; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + free(pFilteringTable); + return IPACM_FAILURE; + } + + if(0 != ioctl(fd, IPA_IOC_GENERATE_FLT_EQ, &flt_eq)) //define and cpy attribute to this struct + { + 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)); + + /* set the bit mask to use MEQ32_IHL offset */ + #ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<7); + #else + flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<8); + #endif + + /* add offset to compare TCP flags */ + 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(&(pFilteringTable->rules[0]), &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(&(pFilteringTable->rules[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + /* add rules */ + if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 1)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + + /* save handle */ + tcp_fin_hdl = pFilteringTable->rules[0].flt_rule_hdl; + tcp_rst_hdl = pFilteringTable->rules[1].flt_rule_hdl; + +fail: + close(fd); + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Wan::delete_tcp_fin_rst_exception_rule() +{ + int len, res = IPACM_SUCCESS; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + + struct ipa_flt_rule_del flt_rule_entry; + + IPACMDBG_H("deleting MHI TCP FIN RST rule \n"); + len = sizeof(struct ipa_ioc_del_flt_rule) + (2 * sizeof(struct ipa_flt_rule_del)); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v4; + pFilteringTable->num_hdls = (uint8_t)2; + + if (tcp_fin_hdl == 0 || tcp_rst_hdl == 0) + { + IPACMERR("invalid tcp_fin_rst_hdl.\n"); + res = IPACM_FAILURE; + goto fail; + } + + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = tcp_fin_hdl; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + flt_rule_entry.hdl = tcp_rst_hdl; + + memcpy(&(pFilteringTable->hdl[1]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to delete MHI TCP FIN RST rule.\n"); + res = IPACM_FAILURE; + goto fail; + } + tcp_fin_hdl = 0; + tcp_rst_hdl = 0; + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} diff --git a/ipacm/src/IPACM_Wlan.cpp b/ipacm/src/IPACM_Wlan.cpp index 427aef3..395f951 100644 --- a/ipacm/src/IPACM_Wlan.cpp +++ b/ipacm/src/IPACM_Wlan.cpp @@ -295,7 +295,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) { if(data->iptype == IPA_IP_v4 || data->iptype == IPA_IP_MAX) { - if(IPACM_Wan::backhaul_is_sta_mode == false) + if(IPACM_Wan::backhaul_mode == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, @@ -318,7 +318,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) memcpy(ipv6_prefix, IPACM_Wan::backhaul_ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix); - if(IPACM_Wan::backhaul_is_sta_mode == false) + if(IPACM_Wan::backhaul_mode == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -350,7 +350,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) { /* handle software routing enable event*/ IPACMDBG_H("IPA_SW_ROUTING_ENABLE for iface: %s \n",IPACM_Iface::ipacmcfg->iface_table[ipa_if_num].iface_name); - handle_software_routing_enable(); + handle_software_routing_enable(false); } } } @@ -366,7 +366,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s xlat_mux_id: %d\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s xlat_mux_id: %d\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name, data_wan_tether->xlat_mux_id); @@ -387,7 +387,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if(is_downstream_set[IPA_IP_v4] == true) { IPACMDBG_H("Downstream was set before, adding UL rules.\n"); - if(data_wan_tether->is_sta == false) + if(data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); handle_wan_up_ex(ext_prop, IPA_IP_v4, @@ -398,7 +398,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) } } #else - if(data_wan_tether->is_sta == false) + if(data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); handle_wan_up_ex(ext_prop, IPA_IP_v4, 0); @@ -418,7 +418,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); #ifndef FEATURE_IPACM_HAL @@ -441,7 +441,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Downstream was set before, adding UL rules.\n"); memcpy(ipv6_prefix, data_wan_tether->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix); - if(data_wan_tether->is_sta == false) + if(data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -453,7 +453,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) } } #else - if(data_wan_tether->is_sta == false) + if(data_wan_tether->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -479,7 +479,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No rx prop.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); #ifndef FEATURE_IPACM_HAL @@ -499,11 +499,11 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) if(is_downstream_set[IPA_IP_v4] == true) { IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); - handle_wan_down(data_wan_tether->is_sta); + handle_wan_down(data_wan_tether->backhaul_type); } } #else - handle_wan_down(data_wan_tether->is_sta); + handle_wan_down(data_wan_tether->backhaul_type); #endif } break; @@ -521,7 +521,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No rx prop.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta, + IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->backhaul_type, data_wan_tether->if_index_tether, IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name); #ifndef FEATURE_IPACM_HAL @@ -543,13 +543,13 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Downstream was set before, deleting UL rules.\n"); /* reset usb-client ipv6 rt-rules */ handle_wlan_client_reset_rt(IPA_IP_v6); - handle_wan_down_v6(data_wan_tether->is_sta); + handle_wan_down_v6(data_wan_tether->backhaul_type); } } #else /* reset usb-client ipv6 rt-rules */ handle_wlan_client_reset_rt(IPA_IP_v6); - handle_wan_down_v6(data_wan_tether->is_sta); + handle_wan_down_v6(data_wan_tether->backhaul_type); #endif } break; @@ -561,6 +561,25 @@ 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); @@ -582,11 +601,12 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) install_ipv6_prefix_flt_rule(ipv6_prefix); } - if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + if (IPACM_Wan::backhaul_mode == Q6_WAN) /* LTE */ { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype); if (data->prefix.iptype == IPA_IP_v4) { + IPACMDBG_H("check getXlat_Mux_Id:%d\n", IPACM_Wan::getXlat_Mux_Id()); handle_wan_up_ex(ext_prop, data->prefix.iptype, IPACM_Wan::getXlat_Mux_Id()); } @@ -620,10 +640,10 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Upstream was set before, deleting UL rules.\n"); if (data->prefix.iptype == IPA_IP_v4) { - handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + handle_wan_down(IPACM_Wan::backhaul_mode); /* LTE STA */ } else { handle_wlan_client_reset_rt(IPA_IP_v6); - handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */ + handle_wan_down_v6(IPACM_Wan::backhaul_mode); /* LTE STA */ } } } @@ -640,10 +660,10 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - if(data_wan->is_sta == false) + if(data_wan->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4); IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id); @@ -664,13 +684,13 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { memcpy(ipv6_prefix, data_wan->ipv6_prefix, sizeof(ipv6_prefix)); install_ipv6_prefix_flt_rule(data_wan->ipv6_prefix); - if(data_wan->is_sta == false) + if(data_wan->backhaul_type == Q6_WAN) { ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6); IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0); @@ -690,12 +710,12 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMERR("No event data is found.\n"); return; } - IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->backhaul_type); if (rx_prop != NULL) { if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX) { - handle_wan_down(data_wan->is_sta); + handle_wan_down(data_wan->backhaul_type); } } break; @@ -712,12 +732,12 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n"); /* reset wifi-client ipv6 rt-rules */ handle_wlan_client_reset_rt(IPA_IP_v6); - IPACMDBG_H("Backhaul is sta mode ? %d\n", data_wan->is_sta); + IPACMDBG_H("Backhaul is sta mode ? %d\n", data_wan->backhaul_type); if (rx_prop != NULL) { if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX) { - handle_wan_down_v6(data_wan->is_sta); + handle_wan_down_v6(data_wan->backhaul_type); } } break; @@ -845,13 +865,13 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) /* handle software routing enable event, iface will update softwarerouting_act to true*/ case IPA_SW_ROUTING_ENABLE: IPACMDBG_H("Received IPA_SW_ROUTING_ENABLE\n"); - IPACM_Iface::handle_software_routing_enable(); + IPACM_Iface::handle_software_routing_enable(false); break; /* handle software routing disable event, iface will update softwarerouting_act to false*/ case IPA_SW_ROUTING_DISABLE: IPACMDBG_H("Received IPA_SW_ROUTING_DISABLE\n"); - IPACM_Iface::handle_software_routing_disable(); + IPACM_Iface::handle_software_routing_disable(false); break; case IPA_WLAN_SWITCH_TO_SCC: @@ -939,7 +959,7 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param) IPACMDBG_H("Received IPA_TETHERING_STATS_UPDATE_EVENT event.\n"); if (IPACM_Wan::isWanUP(ipa_if_num) || IPACM_Wan::isWanUP_V6(ipa_if_num)) { - if(IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */ + if(IPACM_Wan::backhaul_mode == Q6_WAN) /* LTE */ { ipa_get_data_stats_resp_msg_v01 *data = (ipa_get_data_stats_resp_msg_v01 *)param; if (data->ipa_stats_type != QMI_IPA_STATS_TYPE_PIPE_V01) @@ -1441,6 +1461,7 @@ int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type ipt uint32_t tx_index; int wlan_index,v6_num; const int NUM = 1; + bool result; if(tx_prop == NULL) { @@ -1561,8 +1582,19 @@ int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type ipt { rt_rule_entry->rule.hashable = true; } - - if (false == m_routing.AddRoutingRule(rt_rule)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_HW); + result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_HW); + } else { + result = m_routing.AddRoutingRule(rt_rule); + } +#else + result = m_routing.AddRoutingRule(rt_rule); +#endif + if (result == false) { IPACMERR("Routing rule addition failed!\n"); free(rt_rule); @@ -1656,7 +1688,20 @@ int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type ipt #ifdef FEATURE_IPA_V3 rt_rule_entry->rule.hashable = true; #endif - if (false == m_routing.AddRoutingRule(rt_rule)) +#ifdef IPA_IOCTL_SET_FNR_COUNTER_INFO + /* use index hw-counter */ + 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 + DL_HW); + result = m_routing.AddRoutingRule_hw_index(rt_rule, IPACM_Iface::ipacmcfg->hw_counter_offset + DL_HW); + } else { + result = m_routing.AddRoutingRule(rt_rule); + } +#else + result = m_routing.AddRoutingRule(rt_rule); +#endif + + if (result == false) { IPACMERR("Routing rule addition failed!\n"); free(rt_rule); @@ -1667,6 +1712,15 @@ int IPACM_Wlan::handle_wlan_client_route_rule(uint8_t *mac_addr, ipa_ip_type ipt IPACMDBG_H("tx:%d, rt rule hdl=%x ip-type: %d\n", tx_index, get_client_memptr(wlan_client, wlan_index)->wifi_rt_hdl[tx_index].wifi_rt_rule_hdl_v6_wan[v6_num], iptype); + + /* send client-v6 info to pcie modem only with global ipv6 with tx_index = 0 one time*/ + if(is_global_ipv6_addr(get_client_memptr(wlan_client, wlan_index)->v6_addr[v6_num]) && (IPACM_Wan::backhaul_mode == Q6_MHI_WAN)) + { + if (add_connection(wlan_index, v6_num)) + { + IPACMERR("PCIE filter rule addition failed! (%d-client) %d v6-entry\n",wlan_index, v6_num); + } + } } } @@ -1856,8 +1910,8 @@ int IPACM_Wlan::handle_down_evt() /* delete wan filter rule */ if (IPACM_Wan::isWanUP(ipa_if_num) && rx_prop != NULL) { - IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); - IPACM_Lan::handle_wan_down(IPACM_Wan::backhaul_is_sta_mode); + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_mode); + IPACM_Lan::handle_wan_down(IPACM_Wan::backhaul_mode); #ifdef FEATURE_IPA_ANDROID #ifndef FEATURE_IPACM_HAL /* Clean-up tethered-iface list */ @@ -1868,8 +1922,8 @@ int IPACM_Wlan::handle_down_evt() if (IPACM_Wan::isWanUP_V6(ipa_if_num) && rx_prop != NULL) { - IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_is_sta_mode); - handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); + IPACMDBG_H("LAN IF goes down, backhaul type %d\n", IPACM_Wan::backhaul_mode); + handle_wan_down_v6(IPACM_Wan::backhaul_mode); #ifdef FEATURE_IPA_ANDROID /* Clean-up tethered-iface list */ IPACM_Wan::delete_tether_iface(IPA_IP_v6, ipa_if_num); @@ -2070,7 +2124,7 @@ fail: if (softwarerouting_act == true && rx_prop != NULL ) { IPACMDBG_H("Delete sw routing filtering rules\n"); - IPACM_Iface::handle_software_routing_disable(); + IPACM_Iface::handle_software_routing_disable(false); } IPACMDBG_H("finished delete software-routing filtering rules\n "); @@ -2411,3 +2465,148 @@ bool IPACM_Wlan::is_guest_ap() { return m_is_guest_ap; } + +int IPACM_Wlan::add_connection(int client_index, int v6_num) +{ + int len, res = IPACM_SUCCESS; + uint8_t mux_id; + ipa_ioc_add_flt_rule *pFilteringTable = NULL; + int fd; + + mux_id = IPACM_Iface::ipacmcfg->GetQmapId(); + /* contruct filter rules to pcie modem */ + struct ipa_flt_rule_add flt_rule_entry; + ipa_ioc_generate_flt_eq flt_eq; + + IPACMDBG("\n"); + len = sizeof(struct ipa_ioc_add_flt_rule) + sizeof(struct ipa_flt_rule_add); + pFilteringTable = (struct ipa_ioc_add_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_flt_rule_add memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + + pFilteringTable->commit = 1; + pFilteringTable->global = false; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_rules = (uint8_t)1; + + /* Configuring Filtering Rule */ + 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; +#ifdef FEATURE_IPA_V3 + flt_rule_entry.rule.hashable = true; +#endif + flt_rule_entry.rule.attrib.attrib_mask |= IPA_FLT_DST_ADDR; + flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][0]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][1]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][2]; + flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][3]; + 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] = 0xFFFFFFFF; + flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = 0xFFFFFFFF; + + IPACMDBG_H("ipv6 address got: 0x%x:%x:%x:%x\n", get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][0], + get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][1], + get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][2], + get_client_memptr(wlan_client, client_index)->v6_addr[v6_num][3]); + + /* change to network order for modem */ + change_to_network_order(IPA_IP_v6, &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; + + fd = open(IPA_DEVICE_NAME, O_RDWR); + if (fd < 0) + { + IPACMERR("Failed opening %s.\n", IPA_DEVICE_NAME); + free(pFilteringTable); + return IPACM_FAILURE; + } + + if(0 != ioctl(fd, 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)); + memcpy(&(pFilteringTable->rules[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_add)); + + if(false == m_filtering.AddOffloadFilteringRule(pFilteringTable, mux_id, 0)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + + get_client_memptr(wlan_client, client_index)->v6_rt_rule_id[v6_num] = pFilteringTable->rules[0].flt_rule_hdl; + IPACMDBG_H("%d-st client v6_num %d: id handle 0x%x\n", client_index, v6_num, get_client_memptr(wlan_client, client_index)->v6_rt_rule_id[v6_num]); + +fail: + close(fd); + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} + +int IPACM_Wlan::del_connection(int client_index, int v6_num) +{ + int len, res = IPACM_SUCCESS; + ipa_ioc_del_flt_rule *pFilteringTable = NULL; + + struct ipa_flt_rule_del flt_rule_entry; + + IPACMDBG("\n"); + len = sizeof(struct ipa_ioc_del_flt_rule) + sizeof(struct ipa_flt_rule_del); + pFilteringTable = (struct ipa_ioc_del_flt_rule*)malloc(len); + if (pFilteringTable == NULL) + { + IPACMERR("Error Locate ipa_ioc_del_flt_rule memory...\n"); + return IPACM_FAILURE; + } + memset(pFilteringTable, 0, len); + + + pFilteringTable->commit = 1; + pFilteringTable->ip = IPA_IP_v6; + pFilteringTable->num_hdls = (uint8_t)1; + + /* Configuring Software-Routing Filtering Rule */ + memset(&flt_rule_entry, 0, sizeof(struct ipa_flt_rule_del)); + flt_rule_entry.hdl = get_client_memptr(wlan_client, client_index)->v6_rt_rule_id[v6_num]; + + memcpy(&(pFilteringTable->hdl[0]), &flt_rule_entry, sizeof(struct ipa_flt_rule_del)); + + if(false == m_filtering.DelOffloadFilteringRule(pFilteringTable)) + { + IPACMERR("Failed to install WAN DL filtering table.\n"); + res = IPACM_FAILURE; + goto fail; + } + get_client_memptr(wlan_client, client_index)->v6_rt_rule_id[v6_num] = 0; + +fail: + if(pFilteringTable != NULL) + { + free(pFilteringTable); + } + return res; +} diff --git a/ipacm/src/IPACM_Xml.cpp b/ipacm/src/IPACM_Xml.cpp index 4451906..d59bbb0 100644 --- a/ipacm/src/IPACM_Xml.cpp +++ b/ipacm/src/IPACM_Xml.cpp @@ -1,5 +1,5 @@ /* -Copyright (c) 2013, The Linux Foundation. All rights reserved. +Copyright (c) 2013, 2019, The Linux Foundation. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are @@ -75,6 +75,7 @@ static char* IPACM_read_content_element ) { xmlNode* child_ptr; + uint32_t str_len; for (child_ptr = element->children; child_ptr != NULL; @@ -82,7 +83,15 @@ static char* IPACM_read_content_element { if (child_ptr->type == XML_TEXT_NODE) { - return (char*)child_ptr->content; + str_len = strlen((char*)child_ptr->content); + + if(str_len < MAX_XML_STR_LEN) + return (char*)child_ptr->content; + else + { + IPACMERR("Invalid string size\n"); + break; + } } } return NULL; |