diff options
Diffstat (limited to 'msm8998/ipacm/src/IPACM_OffloadManager.cpp')
-rw-r--r-- | msm8998/ipacm/src/IPACM_OffloadManager.cpp | 232 |
1 files changed, 207 insertions, 25 deletions
diff --git a/msm8998/ipacm/src/IPACM_OffloadManager.cpp b/msm8998/ipacm/src/IPACM_OffloadManager.cpp index 332abd5..2061fd2 100644 --- a/msm8998/ipacm/src/IPACM_OffloadManager.cpp +++ b/msm8998/ipacm/src/IPACM_OffloadManager.cpp @@ -45,6 +45,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Z #include "IPACM_ConntrackListener.h" #include "IPACM_Iface.h" #include "IPACM_Config.h" +#include <unistd.h> const char *IPACM_OffloadManager::DEVICE_NAME = "/dev/wwan_ioctl"; @@ -56,16 +57,20 @@ IPACM_OffloadManager::IPACM_OffloadManager() default_gw_index = INVALID_IFACE; upstream_v4_up = false; upstream_v6_up = false; + memset(event_cache, 0, MAX_EVENT_CACHE*sizeof(framework_event_cache)); + latest_cache_index = 0; return ; } RET IPACM_OffloadManager::registerEventListener(IpaEventListener* eventlistener) { RET result = SUCCESS; - if (elrInstance == NULL) + if (elrInstance == NULL) { + IPACMDBG_H("get registerEventListener \n"); + elrInstance = eventlistener; + } else { + IPACMDBG_H("already have EventListener previously, override \n"); elrInstance = eventlistener; - else { - IPACMDBG_H("already register EventListener previously \n"); result = FAIL_INPUT_CHECK; } return SUCCESS; @@ -87,9 +92,12 @@ RET IPACM_OffloadManager::registerCtTimeoutUpdater(ConntrackTimeoutUpdater* time { RET result = SUCCESS; if (touInstance == NULL) + { + IPACMDBG_H("get ConntrackTimeoutUpdater \n"); + touInstance = timeoutupdater; + } else { + IPACMDBG_H("already have ConntrackTimeoutUpdater previously, override \n"); touInstance = timeoutupdater; - else { - IPACMDBG_H("already register ConntrackTimeoutUpdater previously \n"); result = FAIL_INPUT_CHECK; } return SUCCESS; @@ -111,6 +119,8 @@ RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) { IPACM_ConntrackClient *cc; int on = 1, rel; + struct sockaddr_nl local; + unsigned int addr_len; cc = IPACM_ConntrackClient::GetInstance(); @@ -120,8 +130,20 @@ RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) return FAIL_HARDWARE; } + /* check socket name */ + memset(&local, 0, sizeof(struct sockaddr_nl)); + addr_len = sizeof(local); + getsockname(fd, (struct sockaddr *)&local, &addr_len); + IPACMDBG_H(" FD %d, nl_pad %d nl_pid %u\n", fd, local.nl_pad, local.nl_pid); + + /* add the check if getting FDs already or not */ + if(cc->fd_tcp > -1 && cc->fd_udp > -1) { + IPACMDBG_H("has valid FDs fd_tcp %d, fd_udp %d, ignore fd %d.\n", cc->fd_tcp, cc->fd_udp, fd); + return SUCCESS; + } + if (groups == cc->subscrips_tcp) { - cc->fd_tcp = fd; + cc->fd_tcp = dup(fd); IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups); /* set netlink buf */ rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) ); @@ -130,7 +152,7 @@ RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) ); } } else if (groups == cc->subscrips_udp) { - cc->fd_udp = fd; + cc->fd_udp = dup(fd); IPACMDBG_H("Received fd %d with groups %d.\n", fd, groups); /* set netlink buf */ rel = setsockopt(cc->fd_tcp, SOL_NETLINK, NETLINK_NO_ENOBUFS, &on, sizeof(int) ); @@ -150,16 +172,9 @@ RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups) RET IPACM_OffloadManager::clearAllFds() { - IPACM_ConntrackClient *cc; - - cc = IPACM_ConntrackClient::GetInstance(); - if(!cc) - { - IPACMERR("Init clear: cc %p \n", cc); - return FAIL_HARDWARE; - } - cc->UNRegisterWithConnTrack(); + /* IPACM needs to kee old FDs, can't clear */ + IPACMDBG_H("Still use old Fds, can't clear \n"); return SUCCESS; } @@ -181,6 +196,7 @@ RET IPACM_OffloadManager::addDownstream(const char * downstream_name, const Pref ipacm_event_ipahal_stream *evt_data; IPACMDBG_H("addDownstream name(%s), ip-family(%d) \n", downstream_name, prefix.fam); + if (prefix.fam == V4) { IPACMDBG_H("subnet info v4Addr (%x) v4Mask (%x)\n", prefix.v4Addr, prefix.v4Mask); } else { @@ -190,11 +206,69 @@ RET IPACM_OffloadManager::addDownstream(const char * downstream_name, const Pref prefix.v6Mask[0], prefix.v6Mask[1], prefix.v6Mask[2], prefix.v6Mask[3]); } + /* check if netdev valid on device */ if(ipa_get_if_index(downstream_name, &index)) { IPACMERR("fail to get iface index.\n"); + return FAIL_INPUT_CHECK; + } + /* Iface is valid, add to list if not present */ + if (std::find(valid_ifaces.begin(), valid_ifaces.end(), std::string(downstream_name)) == valid_ifaces.end()) + { + /* Iface is new, add it to the list */ + valid_ifaces.push_back(downstream_name); + IPACMDBG_H("add iface(%s) to list\n", downstream_name); + } + + /* check if downstream netdev driver finished its configuration on IPA-HW */ + if (IPACM_Iface::ipacmcfg->CheckNatIfaces(downstream_name)) + { + IPACMDBG_H("addDownstream name(%s) currently not support in ipa \n", downstream_name); + /* copy to the cache */ + for(int i = 0; i < MAX_EVENT_CACHE ;i++) + { + 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; + if(i == MAX_EVENT_CACHE - 1) + { + IPACMDBG_H(" run out of event cache (%d)\n", i); return FAIL_HARDWARE; } + } + + return SUCCESS; + } evt_data = (ipacm_event_ipahal_stream*)malloc(sizeof(ipacm_event_ipahal_stream)); if(evt_data == NULL) @@ -224,12 +298,23 @@ RET IPACM_OffloadManager::removeDownstream(const char * downstream_name, const P ipacm_event_ipahal_stream *evt_data; IPACMDBG_H("removeDownstream name(%s), ip-family(%d) \n", downstream_name, prefix.fam); - if(ipa_get_if_index(downstream_name, &index)) + if(strnlen(downstream_name, sizeof(downstream_name)) == 0) { - IPACMERR("fail to get iface index.\n"); + IPACMERR("iface length is 0.\n"); + return FAIL_HARDWARE; + } + if (std::find(valid_ifaces.begin(), valid_ifaces.end(), std::string(downstream_name)) == valid_ifaces.end()) + { + IPACMERR("iface is not present in list.\n"); return FAIL_HARDWARE; } + if(ipa_get_if_index(downstream_name, &index)) + { + IPACMERR("netdev(%s) already removed, ignored\n", downstream_name); + return SUCCESS; + } + evt_data = (ipacm_event_ipahal_stream*)malloc(sizeof(ipacm_event_ipahal_stream)); if(evt_data == NULL) { @@ -254,8 +339,6 @@ RET IPACM_OffloadManager::removeDownstream(const char * downstream_name, const P RET IPACM_OffloadManager::setUpstream(const char *upstream_name, const Prefix& gw_addr_v4 , const Prefix& gw_addr_v6) { int index; - ipacm_cmd_q_data evt; - ipacm_event_data_addr *evt_data_addr; RET result = SUCCESS; /* if interface name is NULL, default route is removed */ @@ -267,7 +350,6 @@ RET IPACM_OffloadManager::setUpstream(const char *upstream_name, const Prefix& g IPACMERR("no previous upstream set before\n"); return FAIL_INPUT_CHECK; } - if (gw_addr_v4.fam == V4 && upstream_v4_up == true) { IPACMDBG_H("clean upstream(%s) for ipv4-fam(%d) upstream_v4_up(%d)\n", upstream_name, gw_addr_v4.fam, upstream_v4_up); post_route_evt(IPA_IP_v4, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v4); @@ -282,12 +364,60 @@ RET IPACM_OffloadManager::setUpstream(const char *upstream_name, const Prefix& g } else { + /* check if netdev valid on device */ if(ipa_get_if_index(upstream_name, &index)) { IPACMERR("fail to get iface index.\n"); return FAIL_INPUT_CHECK; } + /* check if downstream netdev driver finished its configuration on IPA-HW */ + if (IPACM_Iface::ipacmcfg->CheckNatIfaces(upstream_name)) + { + IPACMDBG_H("setUpstream name(%s) currently not support in ipa \n", upstream_name); + /* copy to the cache */ + for(int i = 0; i < MAX_EVENT_CACHE ;i++) + { + 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 fateway: (%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; + if(i == MAX_EVENT_CACHE - 1) + { + IPACMDBG_H(" run out of event cache (%d) \n", i); + return FAIL_HARDWARE; + } + } + return SUCCESS; + } + /* reset the stats when switch from LTE->STA */ if (index != default_gw_index) { IPACMDBG_H(" interface switched to %s\n", upstream_name); @@ -362,7 +492,24 @@ RET IPACM_OffloadManager::setUpstream(const char *upstream_name, const Prefix& g RET IPACM_OffloadManager::stopAllOffload() { - return SUCCESS; + Prefix v4gw, v6gw; + RET result = SUCCESS; + + memset(&v4gw, 0, sizeof(v4gw)); + memset(&v6gw, 0, sizeof(v6gw)); + v4gw.fam = V4; + v6gw.fam = V6; + IPACMDBG_H("posting setUpstream(NULL), ipv4-fam(%d) ipv6-fam(%d)\n", v4gw.fam, v6gw.fam); + result = setUpstream(NULL, v4gw, v6gw); + + /* reset the event cache */ + default_gw_index = INVALID_IFACE; + upstream_v4_up = false; + upstream_v6_up = false; + memset(event_cache, 0, MAX_EVENT_CACHE*sizeof(framework_event_cache)); + latest_cache_index = 0; + valid_ifaces.clear(); + return result; } RET IPACM_OffloadManager::setQuota(const char * upstream_name /* upstream */, uint64_t mb/* limit */) @@ -386,7 +533,7 @@ RET IPACM_OffloadManager::setQuota(const char * upstream_name /* upstream */, ui return FAIL_INPUT_CHECK; } - IPACMDBG_H("SET_DATA_QUOTA %s %lld", quota.interface_name, mb); + IPACMDBG_H("SET_DATA_QUOTA %s %lu", quota.interface_name, mb); if (ioctl(fd, WAN_IOC_SET_DATA_QUOTA, "a) < 0) { IPACMERR("IOCTL WAN_IOCTL_SET_DATA_QUOTA call failed: %s", strerror(errno)); @@ -427,7 +574,8 @@ RET IPACM_OffloadManager::getStats(const char * upstream_name /* upstream */, offload_stats.tx = stats.tx_bytes; offload_stats.rx = stats.rx_bytes; - IPACMDBG_H("send getStats tx:%lld rx:%lld \n", offload_stats.tx, offload_stats.rx); + IPACMDBG_H("send getStats tx:%lu rx:%lu \n", offload_stats.tx, offload_stats.rx); + close(fd); return SUCCESS; } @@ -482,7 +630,7 @@ int IPACM_OffloadManager::ipa_get_if_index(const char * if_name, int * if_index) } if(strnlen(if_name, sizeof(if_name)) >= sizeof(ifr.ifr_name)) { - IPACMERR("interface name overflows: len %d\n", strnlen(if_name, sizeof(if_name))); + IPACMERR("interface name overflows: len %zu\n", strnlen(if_name, sizeof(if_name))); close(fd); return IPACM_FAILURE; } @@ -528,6 +676,7 @@ int IPACM_OffloadManager::resetTetherStats(const char * upstream_name /* upstrea return FAIL_HARDWARE; } IPACMDBG_H("Reset Interface %s stats\n", upstream_name); + close(fd); return IPACM_SUCCESS; } @@ -538,3 +687,36 @@ IPACM_OffloadManager* IPACM_OffloadManager::GetInstance() return pInstance; } + +bool IPACM_OffloadManager::search_framwork_cache(char * interface_name) +{ + bool rel = 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++) + { + if(event_cache[i].valid == true) + { + //do the compare + if (strncmp(event_cache[i].dev_name, + interface_name, + sizeof(event_cache[i].dev_name)) == 0) + { + 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) + addDownstream(interface_name, event_cache[i].prefix_cache); + else if (event_cache[i].event == IPA_WAN_UPSTREAM_ROUTE_ADD_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); + event_cache[i].valid = false; + rel = true; + } + } + } + IPACMDBG_H(" not found netdev (%s) has cached event\n", interface_name); + return rel; +} |