summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThierry Strudel <tstrudel@google.com>2017-05-23 16:11:15 -0700
committerThierry Strudel <tstrudel@google.com>2017-05-23 22:58:01 -0700
commit582b9e5c388f74eeafad876c81492c81bf1f3945 (patch)
treec6f1f742a3f9554caa3ceb2bc7d37a4f2c31ad1e
parentdb2e7b222236f6aec16f83c5e0ca0878d164ee4e (diff)
downloadipacfg-mgr-582b9e5c388f74eeafad876c81492c81bf1f3945.tar.gz
msm8998: Update to 07.00.00.279.162
msm8998: from vendor/qcom/opensource/data-ipa-cfg-mgr f554a9b Promotion of data.lnx.6.4.9-00026. dc61b57 IPACM: Add support on IPACM-HAL for Android-O e7ba062 hal: deal with unsatisfied dependencies 0b00b18 hal: 1.0: Initial commit Test: build, boot, sanity checks Bug: 62038492 Change-Id: I04f1afb807fb1e43dc52f87963b0713716bc0586 Signed-off-by: Thierry Strudel <tstrudel@google.com>
-rw-r--r--msm8998/hal/Android.mk29
-rw-r--r--msm8998/hal/inc/CtUpdateAmbassador.h62
-rw-r--r--msm8998/hal/inc/HAL.h199
-rw-r--r--msm8998/hal/inc/IOffloadManager.h350
-rw-r--r--msm8998/hal/inc/IpaEventRelay.h55
-rw-r--r--msm8998/hal/inc/LocalLogBuffer.h73
-rw-r--r--msm8998/hal/inc/OffloadStatistics.h49
-rw-r--r--msm8998/hal/inc/PrefixParser.h79
-rw-r--r--msm8998/hal/src/CtUpdateAmbassador.cpp123
-rw-r--r--msm8998/hal/src/HAL.cpp582
-rw-r--r--msm8998/hal/src/IpaEventRelay.cpp83
-rw-r--r--msm8998/hal/src/LocalLogBuffer.cpp126
-rw-r--r--msm8998/hal/src/OffloadStatistics.cpp57
-rw-r--r--msm8998/hal/src/PrefixParser.cpp375
-rw-r--r--msm8998/ipacm/inc/IPACM_ConntrackClient.h7
-rw-r--r--msm8998/ipacm/inc/IPACM_ConntrackListener.h2
-rw-r--r--msm8998/ipacm/inc/IPACM_Defs.h15
-rw-r--r--msm8998/ipacm/inc/IPACM_Lan.h4
-rw-r--r--msm8998/ipacm/inc/IPACM_OffloadManager.h103
-rw-r--r--msm8998/ipacm/inc/IPACM_Wan.h5
-rw-r--r--msm8998/ipacm/src/Android.mk25
-rw-r--r--msm8998/ipacm/src/IPACM_ConntrackClient.cpp70
-rw-r--r--msm8998/ipacm/src/IPACM_ConntrackListener.cpp9
-rw-r--r--msm8998/ipacm/src/IPACM_Conntrack_NATApp.cpp48
-rw-r--r--msm8998/ipacm/src/IPACM_IfaceManager.cpp8
-rw-r--r--msm8998/ipacm/src/IPACM_Lan.cpp342
-rw-r--r--msm8998/ipacm/src/IPACM_Main.cpp45
-rw-r--r--msm8998/ipacm/src/IPACM_OffloadManager.cpp540
-rw-r--r--msm8998/ipacm/src/IPACM_Wan.cpp66
-rw-r--r--msm8998/ipacm/src/IPACM_Wlan.cpp228
-rw-r--r--msm8998/ipacm/src/IPACM_Xml.cpp9
-rw-r--r--msm8998/ipanat/src/Android.mk2
32 files changed, 3615 insertions, 155 deletions
diff --git a/msm8998/hal/Android.mk b/msm8998/hal/Android.mk
new file mode 100644
index 0000000..c24a611
--- /dev/null
+++ b/msm8998/hal/Android.mk
@@ -0,0 +1,29 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+LOCAL_ARM_MODE := arm
+LOCAL_SRC_FILES := src/CtUpdateAmbassador.cpp \
+ src/HAL.cpp \
+ src/IpaEventRelay.cpp \
+ src/LocalLogBuffer.cpp \
+ src/OffloadStatistics.cpp \
+ src/PrefixParser.cpp
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/inc
+LOCAL_MODULE := liboffloadhal
+LOCAL_CPP_FLAGS := -Wall -Werror
+LOCAL_SHARED_LIBRARIES := libhwbinder \
+ libhidlbase \
+ libhidltransport \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libhardware_legacy \
+ libhardware \
+ android.hardware.tetheroffload.config@1.0 \
+ android.hardware.tetheroffload.control@1.0
+LOCAL_VENDOR_MODULE := true
+LOCAL_MODULE_PATH_32 := $(TARGET_OUT_VENDOR)/lib
+LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
+include $(BUILD_SHARED_LIBRARY)
diff --git a/msm8998/hal/inc/CtUpdateAmbassador.h b/msm8998/hal/inc/CtUpdateAmbassador.h
new file mode 100644
index 0000000..d4890f3
--- /dev/null
+++ b/msm8998/hal/inc/CtUpdateAmbassador.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _CT_UPDATE_AMBASSADOR_H_
+#define _CT_UPDATE_AMBASSADOR_H_
+/* External Includes */
+#include <hidl/HidlTransportSupport.h>
+
+/* HIDL Includes */
+#include <android/hardware/tetheroffload/control/1.0/ITetheringOffloadCallback.h>
+
+/* Internal Includes */
+#include "IOffloadManager.h"
+
+/* Namespace pollution avoidance */
+using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+using ::android::hardware::tetheroffload::control::V1_0::NetworkProtocol;
+using HALIpAddrPortPair = ::android::hardware::tetheroffload::control::V1_0::IPv4AddrPortPair;
+using HALNatTimeoutUpdate = ::android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate;
+
+using IpaIpAddrPortPair = ::IOffloadManager::ConntrackTimeoutUpdater::IpAddrPortPair;
+using IpaNatTimeoutUpdate = ::IOffloadManager::ConntrackTimeoutUpdater::NatTimeoutUpdate;
+using IpaL4Protocol = ::IOffloadManager::ConntrackTimeoutUpdater::L4Protocol;
+
+
+class CtUpdateAmbassador : public IOffloadManager::ConntrackTimeoutUpdater {
+public:
+ CtUpdateAmbassador(const ::android::sp<ITetheringOffloadCallback>& /* cb */);
+ /* ------------------- CONNTRACK TIMEOUT UPDATER ------------------------ */
+ void updateTimeout(IpaNatTimeoutUpdate /* update */);
+private:
+ static bool translate(IpaNatTimeoutUpdate /* in */, HALNatTimeoutUpdate& /* out */);
+ static bool translate(IpaIpAddrPortPair /* in */, HALIpAddrPortPair& /* out */);
+ static bool L4ToNetwork(IpaL4Protocol /* in */, NetworkProtocol& /* out */);
+ const ::android::sp<ITetheringOffloadCallback>& mFramework;
+}; /* CtUpdateAmbassador */
+#endif /* _CT_UPDATE_AMBASSADOR_H_ */ \ No newline at end of file
diff --git a/msm8998/hal/inc/HAL.h b/msm8998/hal/inc/HAL.h
new file mode 100644
index 0000000..622a67e
--- /dev/null
+++ b/msm8998/hal/inc/HAL.h
@@ -0,0 +1,199 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _HAL_H_
+#define _HAL_H_
+
+/* HIDL Includes */
+#include <android/hardware/tetheroffload/config/1.0/IOffloadConfig.h>
+#include <android/hardware/tetheroffload/control/1.0/IOffloadControl.h>
+#include <hidl/HidlTransportSupport.h>
+
+/* External Includes */
+#include <string>
+#include <vector>
+
+/* Internal Includes */
+#include "CtUpdateAmbassador.h"
+#include "IOffloadManager.h"
+#include "IpaEventRelay.h"
+#include "LocalLogBuffer.h"
+
+/* Avoid the namespace litering everywhere */
+using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
+using ::android::hardware::Return;
+using ::android::hardware::hidl_handle;
+using ::android::hardware::hidl_string;
+using ::android::hardware::hidl_vec;
+
+using RET = ::IOffloadManager::RET;
+using Prefix = ::IOffloadManager::Prefix;
+
+using ::std::map;
+using ::std::string;
+using ::std::vector;
+
+using ::android::hardware::tetheroffload::config::V1_0::IOffloadConfig;
+using ::android::hardware::tetheroffload::control::V1_0::IOffloadControl;
+
+using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+
+
+class HAL : public IOffloadControl, IOffloadConfig {
+public:
+ /* Static Const Definitions */
+ static const uint32_t UDP_SUBSCRIPTIONS =
+ NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY;
+ static const uint32_t TCP_SUBSCRIPTIONS =
+ NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY;
+
+ /* Interface to IPACM */
+ /**
+ * @TODO This will likely need to be extended into a proper FactoryPattern
+ * when version bumps are needed.
+ *
+ * This makeIPAHAL function would move to a HALFactory class. Each HAL could
+ * then be versioned (class HAL_V1, class HAL_V2, etc) and inherit from a base class HAL.
+ * Then the version number in this function could be used to decide which one to return
+ * (if any).
+ *
+ * IPACM does not need to talk directly back to the returned HAL class. The other methods that
+ * IPACM needs to call are covered by registering the event listeners. If IPACM did need to
+ * talk directly back to the HAL object, without HAL registering a callback, these methods would
+ * need to be defined in the HAL base class.
+ *
+ * This would slightly break backwards compatibility so it should be discouraged; however, the
+ * base class could define a sane default implementation and not require that the child class
+ * implement this new method. This "sane default implementation" might only be possible in the
+ * case of listening to async events; if IPACM needs to query something, then this would not
+ * be backwards compatible and should be done via registering a callback so that IPACM knows
+ * this version of HAL supports that functionality.
+ *
+ * The above statements assume that only one version of the HAL will be instantiated at a time.
+ * Yet, it seems possible that a HAL_V1 and HAL_V2 service could both be registered, extending
+ * support to both old and new client implementations. It would be difficult to multiplex
+ * information from both versions. Additionally, IPACM would be responsible for instantiating
+ * two HALs (makeIPAHAL(1, ...); makeIPAHAL(2, ...)) which makes signaling between HAL versions
+ * (see next paragraph) slightly more difficult but not impossible.
+ *
+ * If concurrent versions of HAL are required, there will likely need to only be one master.
+ * Whichever version of HAL receives a client first may be allowed to take over control while
+ * other versions would be required to return failures (ETRYAGAIN: another version in use) until
+ * that version of the client relinquishes control. This should work seemlessly because we
+ * currently have an assumption that only one client will be present in system image.
+ * Logically, that client will have only a single version (or if it supports multiple, it will
+ * always attempt the newest version of HAL before falling back) and therefore no version
+ * collisions could possibly occur.
+ *
+ * Dislaimer:
+ * ==========
+ * Supporting multiple versions of an interface, in the same code base, at runtime, comes with a
+ * significant carrying cost and overhead in the form of developer headaches. This should not
+ * be done lightly and should be extensively scoped before committing to the effort.
+ *
+ * Perhaps the notion of minor version could be introduced to bridge the gaps created above.
+ * For example, 1.x and 1.y could be ran concurrently and supported from the same IPACM code.
+ * Yet, a major version update, would not be backwards compatible. This means that a 2.x HAL
+ * could not linked into the same IPACM code base as a 1.x HAL.
+ */
+ static HAL* makeIPAHAL(int /* version */, IOffloadManager* /* mgr */);
+
+ /* IOffloadConfig */
+ Return<void> setHandles(
+ const hidl_handle& /* fd1 */,
+ const hidl_handle& /* fd2 */,
+ setHandles_cb /* hidl_cb */);
+
+ /* IOffloadControl */
+ Return<void> initOffload(
+ const ::android::sp<ITetheringOffloadCallback>& /* cb */,
+ initOffload_cb /* hidl_cb */);
+ Return<void> stopOffload(
+ stopOffload_cb /* hidl_cb */);
+ Return<void> setLocalPrefixes(
+ const hidl_vec<hidl_string>& /* prefixes */,
+ setLocalPrefixes_cb /* hidl_cb */);
+ Return<void> getForwardedStats(
+ const hidl_string& /* upstream */,
+ getForwardedStats_cb /* hidl_cb */);
+ Return<void> setDataLimit(
+ const hidl_string& /* upstream */,
+ uint64_t /* limit */,
+ setDataLimit_cb /* hidl_cb */);
+ Return<void> setUpstreamParameters(
+ const hidl_string& /* iface */,
+ const hidl_string& /* v4Addr */,
+ const hidl_string& /* v4Gw */,
+ const hidl_vec<hidl_string>& /* v6Gws */,
+ setUpstreamParameters_cb /* hidl_cb */);
+ Return<void> addDownstream(
+ const hidl_string& /* iface */,
+ const hidl_string& /* prefix */,
+ addDownstream_cb /* hidl_cb */);
+ Return<void> removeDownstream(
+ const hidl_string& /* iface */,
+ const hidl_string& /* prefix */,
+ removeDownstream_cb /* hidl_cb */);
+
+private:
+ typedef struct BoolResult {
+ bool success;
+ string errMsg;
+ } boolResult_t;
+
+ HAL(IOffloadManager* /* mgr */);
+ void registerAsSystemService(const char* /* name */);
+
+ void doLogcatDump();
+
+ static BoolResult makeInputCheckFailure(string /* customErr */);
+ static BoolResult ipaResultToBoolResult(RET /* in */);
+
+ static vector<string> convertHidlStrToStdStr(hidl_vec<hidl_string> /* in */);
+
+ void registerEventListeners();
+ void registerIpaCb();
+ void registerCtCb();
+ void unregisterEventListeners();
+ void unregisterIpaCb();
+ void unregisterCtCb();
+
+ void clearHandles();
+
+ bool isInitialized();
+
+ IOffloadManager* mIPA;
+ hidl_handle mHandle1;
+ hidl_handle mHandle2;
+ LocalLogBuffer mLogs;
+ ::android::sp<ITetheringOffloadCallback> mCb;
+ IpaEventRelay *mCbIpa;
+ CtUpdateAmbassador *mCbCt;
+}; /* HAL */
+#endif /* _HAL_H_ */
diff --git a/msm8998/hal/inc/IOffloadManager.h b/msm8998/hal/inc/IOffloadManager.h
new file mode 100644
index 0000000..6a357b3
--- /dev/null
+++ b/msm8998/hal/inc/IOffloadManager.h
@@ -0,0 +1,350 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _I_OFFLOAD_MANAGER_H_
+#define _I_OFFLOAD_MANAGER_H_
+
+/* External Includes */
+#include <sys/types.h>
+
+/* Internal Includes */
+#include "OffloadStatistics.h"
+
+
+class IOffloadManager {
+public:
+ enum RET {
+ FAIL_TOO_MANY_PREFIXES = -6,
+ FAIL_UNSUPPORTED = -5,
+ FAIL_INPUT_CHECK = -4,
+ FAIL_HARDWARE = -3,
+ FAIL_UNNEEDED = -2,
+ FAIL_TRY_AGAIN = -1,
+ SUCCESS = 0,
+ SUCCESS_DUPLICATE_CONFIG = 1,
+ SUCCESS_NO_OP = 2,
+ SUCCESS_OPTIMIZED = 3
+ }; /* RET */
+
+ enum IP_FAM {
+ V4 = 0,
+ V6 = 1,
+ INVALID = 2
+ }; /* IP_FAM */
+
+ /* Overloading to use for addresses as well */
+ typedef struct Prefix {
+ IP_FAM fam;
+ uint32_t v4Addr;
+ uint32_t v4Mask;
+ uint32_t v6Addr[4];
+ uint32_t v6Mask[4];
+ } prefix_t;
+
+ /* ---------------------------- LIFECYCLE ------------------------------- */
+ virtual ~IOffloadManager(){}
+
+ /* ---------------------- ASYNC EVENT CALLBACKS ------------------------- */
+ class IpaEventListener {
+ public:
+ enum StoppedReason {
+ /**
+ * Offload was stopped due to the configuration being removed via
+ * setUpstreamParameters/removeDownstream.
+ */
+ REQUESTED,
+ /**
+ * Offload was stopped due to an internal (to IPA or modem) error.
+ *
+ * Statistics may be temporarily unavailable.
+ */
+ ERROR,
+ /**
+ * Offload was stopped because the upstream connection has
+ * migrated to unsupported radio access technology.
+ *
+ * Statistics will still be available.
+ */
+ UNSUPPORTED
+ }; /* StoppedReason */
+ virtual ~IpaEventListener(){}
+ /**
+ * Called when Offload first begins to occur on any upstream and
+ * tether interface pair. It should be paired with an onOffloadStopped
+ * call.
+ */
+ virtual void onOffloadStarted(){}
+ /**
+ * Called when Offload stops occurring on all upstream and tether
+ * interface pairs. It comes after a call to onOffloadStarted.
+ *
+ * @param reason Reason that Offload was stopped
+ */
+ virtual void onOffloadStopped(StoppedReason /* reason */){}
+ /**
+ * Called when the hardware can support Offload again.
+ *
+ * Any statistics that were previously unavailable, may be queried
+ * again at this time.
+ */
+ virtual void onOffloadSupportAvailable(){}
+ /**
+ * Called when the limit set via setQuota has expired.
+ *
+ * It is implied that Offload has been stopped on all upstream and
+ * tether interface pairs when this callback is called.
+ */
+ virtual void onLimitReached(){}
+ }; /* IpaEventListener */
+
+ /**
+ * Request notifications about asynchronous events that occur in hardware.
+ *
+ * The calling client must be able to handle the callback on a separate
+ * thread (i.e. their implementation of IpaEventListener must be thread
+ * safe).
+ *
+ * @return SUCCESS iff callback successfully registered
+ *
+ * Remarks: This can't really be allowed to fail.
+ */
+ virtual RET registerEventListener(IpaEventListener* /* listener */) = 0;
+ /**
+ * Unregister a previously registered listener.
+ *
+ * @return SUCCESS iff callback successfully unregistered
+ * FAIL_INPUT_CHECK if callback was never registered
+ */
+ virtual RET unregisterEventListener(IpaEventListener* /* listener */) = 0;
+
+ class ConntrackTimeoutUpdater {
+ public:
+ enum L4Protocol {
+ TCP = 0,
+ UDP = 1
+ }; /* L4Protocol */
+ typedef struct IpAddrPortPair {
+ uint32_t ipAddr;
+ uint16_t port;
+ } ipAddrPortPair_t;
+ typedef struct NatTimeoutUpdate {
+ IpAddrPortPair src;
+ IpAddrPortPair dst;
+ L4Protocol proto;
+ } natTimeoutUpdate_t;
+ virtual ~ConntrackTimeoutUpdater(){}
+ virtual void updateTimeout(NatTimeoutUpdate /* update */) {}
+ }; /* ConntrackTimeoutUpdater */
+
+ /**
+ * Register a callback that may be called if the OffloadManager wants to
+ * update the timeout value in conntrack of kernel.
+ *
+ * The calling client must be able to handle the callback on a separate
+ * thread (i.e. their implementation of ConntrackTimeoutUpdater must be
+ * thread safe)
+ *
+ * @return SUCCESS iff callback successfully registered
+ *
+ * Remarks: This can't really be allowed to fail
+ */
+ virtual RET registerCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0;
+ /**
+ * Unregister a previously registered callback.
+ *
+ * @return SUCCESS iff callback successfully unregistered
+ * FAIL_INPUT_CHECK if callback was never registered
+ */
+ virtual RET unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */) = 0;
+
+ /* ----------------------------- CONFIG --------------------------------- */
+ /**
+ * Provide a file descriptor for use with conntrack library
+ *
+ * @param fd File Descriptor that has been opened and bound to groups
+ * @param groups Groups (bit mask) that fd has been bound to
+ *
+ * @return SUCCESS iff IOffloadManager needed this file descriptor and
+ * it was properly bound.
+ * FAIL_INPUT_CHECK if IOffloadManager needed this file descriptor
+ * but it was found to not be properly bound
+ * FAIL_UNNEEDED if IOffloadManager determined that it does not need
+ * a file descriptor bound to these groups.
+ */
+ virtual RET provideFd(int /* fd */, unsigned int /* group */) = 0;
+ /**
+ * Indicate that IOffloadManager <b>must</b> cease using all file
+ * descriptors passed via provideFd API.
+ *
+ * After this call returns, the file descriptors will likely be closed by
+ * the calling client.
+ *
+ * @return SUCCESS iff IOffloadManager has stopped using all file
+ * descriptors
+ * FAIL_TRY_AGAIN if IOffloadManager needs more time with these
+ * file descriptors before it can release them
+ *
+ * Remarks: Currently, it would be very difficult to handle a FAIL_TRY_AGAIN
+ * because HAL serivce does not own a thread outside of RPC
+ * Threadpool to reschedule this call.
+ */
+ virtual RET clearAllFds() = 0;
+ /**
+ * Query whether STA+AP offload is supported on this device.
+ *
+ * @return true if supported, false otherwise
+ */
+ virtual bool isStaApSupported() = 0;
+
+ /* ------------------------------ ROUTE --------------------------------- */
+ /**
+ * Add a downstream prefix that <i>may</i> be forwarded.
+ *
+ * The Prefix may be an IPv4 or IPv6 address to signify which family can be
+ * offloaded from the specified tether interface. If the given IP family,
+ * as determined by the Prefix, has a corresponding upstream configured,
+ * then traffic should be forwarded between the two interfaces.
+ *
+ * Only traffic that has a downstream address within the specified Prefix
+ * can be forwarded. Traffic from the same downstream interface that falls
+ * outside of the Prefix will be unaffected and can be forwarded iff it was
+ * previously configured via a separate addDownstream call.
+ *
+ * If no upstream has been configured, then this information must be cached
+ * so that offload may begin once an upstream is configured.
+ *
+ * This API does <b>not</b> replace any previously configured downstreams
+ * and must be explicitly removed by calling removeDownstream or by clearing
+ * the entire configuration by calling stopAllOffload.
+ *
+ * @return SUCCESS The new information was accepted
+ * FAIL_TOO_MANY_PREFIXES The hardware has already accepted the max
+ * number of Prefixes that can be supported.
+ * If offload is desired on this Prefix then
+ * another must be removed first.
+ * FAIL_UNSUPPORTED The hardware cannot forward traffic from this
+ * downstream interface and will never be able to.
+ */
+ virtual RET addDownstream(const char* /* downstream */,
+ const Prefix& /* prefix */) = 0;
+ /**
+ * Remove a downstream Prefix that forwarding was previously requested for.
+ *
+ * The Prefix may be an IPv4 or IPv6 address. Traffic outside of this
+ * Prefix is not affected.
+ *
+ * @return SUCCESS iff forwarding was previously occurring and has been
+ * stopped
+ * SUCCESS_NO_OP iff forwarding was not previously occurring and
+ * therefore no action needed to be taken
+ */
+ virtual RET removeDownstream(const char* /* downstream */,
+ const Prefix& /* prefix */) = 0;
+ /**
+ * Indicate that hardware should forward traffic from any configured
+ * downstreams to the specified upstream.
+ *
+ * When iface is non-null and non-empty and v4Gw is valid, then any
+ * currently configured or future configured IPv4 downstreams should be
+ * forwarded to this upstream interface.
+ *
+ * When iface is non-null and non-empty and v6Gw is valid, then any
+ * currently configured or future configured IPv6 downstreams should be
+ * forwarded to this upstream interface.
+ *
+ * @param iface Upstream interface name. Only one is needed because IPv4
+ * and IPv6 interface names are required to match.
+ * @param v4Gw The address of the IPv4 Gateway on the iface
+ * @param v6Gw The address of one of the IPv6 Gateways on the iface
+ *
+ * @return SUCCESS iff the specified configuration was applied
+ * SUCCESS_DUPLICATE_CONFIG if this configuration <i>exactly</i>
+ * matches a previously provided
+ * configuration. This means that no
+ * action has to be taken, but, the
+ * configuration was previously accepted
+ * and applied.
+ * FAIL_UNSUPPORTED if hardware cannot support forwarding to this
+ * upstream interface
+ *
+ * Remarks: This overrides any previously configured parameters
+ */
+ virtual RET setUpstream(const char* /* iface */, const Prefix& /* v4Gw */,
+ const Prefix& /* v6Gw */) = 0;
+ /**
+ * All traffic must be returned to the software path and all configuration
+ * (including provided file descriptors) must be forgotten.
+ *
+ * @return SUCCESS If all offload was successfully stopped and provided
+ * file descriptors were released.
+ *
+ * Remarks: This can't really fail?
+ */
+ virtual RET stopAllOffload() = 0;
+
+ /* --------------------------- STATS/POLICY ----------------------------- */
+ /**
+ * Instruct hardware to stop forwarding traffic and send a callback after
+ * limit bytes have been transferred in either direction on this upstream
+ * interface.
+ *
+ * @param upstream Upstream interface name that the limit should apply to
+ * @param limit Bytes limit that can occur before action should be taken
+ *
+ * @return SUCCESS If the limit was successfully applied
+ * SUCCESS_OPTIMIZED If the limit was sufficiently high to be
+ * interpreted as "no quota".
+ * FAIL_HARDWARE If the limit was rejected by the hardware
+ * FAIL_UNSUPPORTED If metering is not supported on this interface
+ * FAIL_TRY_AGAIN If this upstream has not been previously
+ * configured to allow offload
+ * (via setUpstreamParameters)
+ */
+ virtual RET setQuota(const char* /* upstream */, uint64_t /* limit */) = 0;
+ /**
+ * Query for statistics counters in hardware.
+ *
+ * This returns an aggregate of all hardware accelerated traffic which
+ * has occurred on this upstream interface.
+ *
+ * @param upstream Interface on which traffic entered/exited
+ * @param reset Whether hardware counters should reset after returning
+ * current statistics
+ * @param ret Output variable where statistics are returned
+ *
+ * @return SUCCESS If the statistics were successfully populated in ret and
+ * were successfully reset if requested.
+ * FAIL_TRY_AGAIN If the statistics are not currently available but
+ * may be available later. This may occur during
+ * a subsystem restart.
+ * FAIL_UNSUPPORTED If statistics are not supported on this upstream
+ */
+ virtual RET getStats(const char* /* upstream */, bool /* reset */,
+ OffloadStatistics& /* ret */) = 0;
+}; /* IOffloadManager */
+#endif /* _I_OFFLOAD_MANAGER_H_ */
diff --git a/msm8998/hal/inc/IpaEventRelay.h b/msm8998/hal/inc/IpaEventRelay.h
new file mode 100644
index 0000000..4541510
--- /dev/null
+++ b/msm8998/hal/inc/IpaEventRelay.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _IPA_EVENT_RELAY_H_
+#define _IPA_EVENT_RELAY_H_
+/* External Includes */
+#include <hidl/HidlTransportSupport.h>
+
+/* HIDL Includes */
+#include <android/hardware/tetheroffload/control/1.0/ITetheringOffloadCallback.h>
+
+/* Internal Includes */
+#include "IOffloadManager.h"
+
+/* Namespace pollution avoidance */
+using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+
+
+class IpaEventRelay : public IOffloadManager::IpaEventListener {
+public:
+ IpaEventRelay(const ::android::sp<ITetheringOffloadCallback>& /* cb */);
+ /* ----------------------- IPA EVENT LISTENER --------------------------- */
+ void onOffloadStarted();
+ void onOffloadStopped(StoppedReason /* reason */);
+ void onOffloadSupportAvailable();
+ void onLimitReached();
+private:
+ const ::android::sp<ITetheringOffloadCallback>& mFramework;
+}; /* IpaEventRelay */
+#endif /* _IPA_EVENT_RELAY_H_ */ \ No newline at end of file
diff --git a/msm8998/hal/inc/LocalLogBuffer.h b/msm8998/hal/inc/LocalLogBuffer.h
new file mode 100644
index 0000000..c23ef7d
--- /dev/null
+++ b/msm8998/hal/inc/LocalLogBuffer.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _LOCAL_LOG_BUFFER_H_
+#define _LOCAL_LOG_BUFFER_H_
+/* External Includes */
+#include <deque>
+#include <sstream>
+#include <string>
+#include <sys/types.h>
+#include <vector>
+
+/* Namespace pollution avoidance */
+using ::std::deque;
+using ::std::string;
+using ::std::stringstream;
+using ::std::vector;
+
+
+class LocalLogBuffer {
+public:
+ class FunctionLog {
+ public:
+ FunctionLog(string /* funcName */);
+ FunctionLog(const FunctionLog& /* other */);
+ void addArg(string /* kw */, string /* arg */);
+ void addArg(string /* kw */, vector<string> /* args */);
+ void addArg(string /* kw */, uint64_t /* arg */);
+ void setResult(bool /* success */, string /* msg */);
+ void setResult(vector<unsigned int> /* ret */);
+ void setResult(uint64_t /* rx */, uint64_t /* tx */);
+ string toString();
+ private:
+ void maybeAddArgsComma();
+ const string mName;
+ bool mArgsProvided;
+ stringstream mSSArgs;
+ stringstream mSSReturn;
+ }; /* FunctionLog */
+ LocalLogBuffer(string /* name */, int /* maxLogs */);
+ void addLog(FunctionLog /* log */);
+ void toLogcat();
+private:
+ deque<FunctionLog> mLogs;
+ const string mName;
+ const size_t mMaxLogs;
+}; /* LocalLogBuffer */
+#endif /* _LOCAL_LOG_BUFFER_H_ */ \ No newline at end of file
diff --git a/msm8998/hal/inc/OffloadStatistics.h b/msm8998/hal/inc/OffloadStatistics.h
new file mode 100644
index 0000000..226ea72
--- /dev/null
+++ b/msm8998/hal/inc/OffloadStatistics.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _OFFLOAD_STATISTICS_H_
+#define _OFFLOAD_STATISTICS_H_
+
+#include <string>
+#include <sys/types.h>
+
+
+class OffloadStatistics {
+public:
+ uint64_t rx;
+ uint64_t tx;
+
+ OffloadStatistics();
+ OffloadStatistics(std::string /* upstream */);
+
+ uint64_t getTotalRxBytes();
+ uint64_t getTotalTxBytes();
+private:
+ std::string upstream;
+}; /* OffloadStatistics */
+#endif /* _OFFLOAD_STATISTICS_H_ */
diff --git a/msm8998/hal/inc/PrefixParser.h b/msm8998/hal/inc/PrefixParser.h
new file mode 100644
index 0000000..4682aa5
--- /dev/null
+++ b/msm8998/hal/inc/PrefixParser.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _PREFIX_PARSER_H_
+#define _PREFIX_PARSER_H_
+
+/* External Includes */
+#include <string.h>
+#include <sys/types.h>
+#include <vector>
+
+/* Internal Includes */
+#include "IOffloadManager.h"
+
+/* Avoiding namespace pollution */
+using IP_FAM = ::IOffloadManager::IP_FAM;
+using Prefix = ::IOffloadManager::Prefix;
+
+using ::std::string;
+using ::std::vector;
+
+
+class PrefixParser {
+public:
+ PrefixParser();
+ bool add(vector<string> /* in */);
+ bool add(string /* in */);
+ bool addV4(vector<string> /* in */);
+ bool addV4(string /* in */);
+ bool addV6(vector<string> /* in */);
+ bool addV6(string /* in */);
+ int size();
+ bool allAreFullyQualified();
+ Prefix getFirstPrefix();
+ string getLastErrAsStr();
+private:
+ bool add(string /* in */, IP_FAM /* famHint */);
+ bool add(vector<string> /* in */, IP_FAM /* famHint */);
+ static IP_FAM guessIPFamily(string /* in */);
+ static bool splitIntoAddrAndMask(string /* in */, string& /* addr */,
+ string& /* mask */);
+ static int parseSubnetMask(string /* in */, IP_FAM /* famHint */);
+ static bool parseV4Addr(string /* in */, Prefix& /* out */);
+ static bool parseV6Addr(string /* in */, Prefix& /* out */);
+ static bool populateV4Mask(int /* mask */, Prefix& /* out */);
+ static bool populateV6Mask(int /* mask */, Prefix& /* out */);
+ static uint32_t createMask(int /* mask */);
+ static Prefix makeBlankPrefix(IP_FAM /* famHint */);
+ bool isMaskValid(int /* mask */, IP_FAM /* fam */);
+ static const uint32_t FULLY_QUALIFIED_MASK = ~0;
+ vector<Prefix> mPrefixes;
+ string mLastErr;
+}; /* PrefixParser */
+#endif /* _PREFIX_PARSER_H_ */ \ No newline at end of file
diff --git a/msm8998/hal/src/CtUpdateAmbassador.cpp b/msm8998/hal/src/CtUpdateAmbassador.cpp
new file mode 100644
index 0000000..4843fe2
--- /dev/null
+++ b/msm8998/hal/src/CtUpdateAmbassador.cpp
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DBG
+ #define DBG false
+#endif /* DBG */
+#define LOG_TAG "IPAHALService/CtUpdateAmbassador"
+
+/* External Includes */
+#include <arpa/inet.h>
+#include <cutils/log.h>
+
+/* HIDL Includes */
+#include <android/hardware/tetheroffload/control/1.0/ITetheringOffloadCallback.h>
+
+/* Internal Includes */
+#include "CtUpdateAmbassador.h"
+
+/* Namespace pollution avoidance */
+using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+using ::android::hardware::tetheroffload::control::V1_0::NetworkProtocol;
+using HALIpAddrPortPair = ::android::hardware::tetheroffload::control::V1_0::IPv4AddrPortPair;
+using HALNatTimeoutUpdate = ::android::hardware::tetheroffload::control::V1_0::NatTimeoutUpdate;
+
+using IpaIpAddrPortPair = ::IOffloadManager::ConntrackTimeoutUpdater::IpAddrPortPair;
+using IpaNatTimeoutUpdate = ::IOffloadManager::ConntrackTimeoutUpdater::NatTimeoutUpdate;
+using IpaL4Protocol = ::IOffloadManager::ConntrackTimeoutUpdater::L4Protocol;
+
+
+CtUpdateAmbassador::CtUpdateAmbassador(
+ const ::android::sp<ITetheringOffloadCallback>& cb) : mFramework(cb) {
+} /* CtUpdateAmbassador */
+
+void CtUpdateAmbassador::updateTimeout(IpaNatTimeoutUpdate in) {
+ if (DBG) {
+ ALOGD("updateTimeout(src={%#010X, %#04X}, dest={%#010X, %#04X}, Proto=%d)",
+ in.src.ipAddr, in.src.port, in.dst.ipAddr, in.dst.port,
+ in.proto);
+ }
+ HALNatTimeoutUpdate out;
+ if (!translate(in, out)) {
+ /* Cannot log the input outside of DBG flag because it contains sensitive
+ * information. This will lead to a two step debug if the information
+ * cannot be gleaned from IPACM logs. The other option is to improve this
+ * with the use of our local log. That would likely still be hard to
+ * instruct testers to collect logs, because, assuming timeout updates
+ * are numerous, it will overrun the ring quickly. Therefore, the tester
+ * would have to know the exact moment as issue occurred. Or we make the
+ * ring massive. This would lead to a significant memory overhead.
+ * Because of this overhead, we would likely not want to check in a change
+ * with it and once we provide a debug build for increasing buffer size,
+ * why not just define the DBG flag?
+ */
+ ALOGE("Failed to translate timeout event :(");
+ } else {
+ mFramework->updateTimeout(out);
+ }
+} /* updateTimeout */
+
+bool CtUpdateAmbassador::translate(IpaNatTimeoutUpdate in, HALNatTimeoutUpdate &out) {
+ return translate(in.src, out.src)
+ && translate(in.dst, out.dst)
+ && L4ToNetwork(in.proto, out.proto);
+} /* translate */
+
+bool CtUpdateAmbassador::translate(IpaIpAddrPortPair in, HALIpAddrPortPair& out) {
+ char ipAddrStr[INET_ADDRSTRLEN];
+
+ if (inet_ntop(AF_INET, &(in.ipAddr), ipAddrStr, INET_ADDRSTRLEN) == nullptr) {
+ /* errno would be valid here with EAFNOSUPPORT or ENOSPC, neither should really
+ * be possible in our scenario though.
+ */
+ return false;
+ }
+
+ out.addr = ipAddrStr;
+ out.port = in.port;
+
+ return true;
+} /* translate */
+
+bool CtUpdateAmbassador::L4ToNetwork(IpaL4Protocol in, NetworkProtocol &out) {
+ bool ret = false;
+ switch(in) {
+ case IpaL4Protocol::TCP:
+ ret = true;
+ out = NetworkProtocol::TCP;
+ break;
+ case IpaL4Protocol::UDP:
+ ret = true;
+ out = NetworkProtocol::UDP;
+ break;
+ default:
+ ret = false;
+ break;
+ }
+ return ret;
+} /* L4ToNetwork */
diff --git a/msm8998/hal/src/HAL.cpp b/msm8998/hal/src/HAL.cpp
new file mode 100644
index 0000000..0d25aa0
--- /dev/null
+++ b/msm8998/hal/src/HAL.cpp
@@ -0,0 +1,582 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef DBG
+ #define DBG true
+#endif /* DBG */
+#define LOG_TAG "IPAHALService"
+
+/* HIDL Includes */
+#include <hwbinder/IPCThreadState.h>
+#include <hwbinder/ProcessState.h>
+
+/* Kernel Includes */
+#include <linux/netfilter/nfnetlink_compat.h>
+
+/* External Includes */
+#include <cutils/log.h>
+#include <string>
+#include <sys/types.h>
+#include <vector>
+
+/* Internal Includes */
+#include "HAL.h"
+#include "LocalLogBuffer.h"
+#include "PrefixParser.h"
+
+/* Namespace pollution avoidance */
+using ::android::hardware::Void;
+using ::android::status_t;
+
+using RET = ::IOffloadManager::RET;
+using Prefix = ::IOffloadManager::Prefix;
+
+using ::std::map;
+using ::std::vector;
+
+
+/* ------------------------------ PUBLIC ------------------------------------ */
+HAL* HAL::makeIPAHAL(int version, IOffloadManager* mgr) {
+ if (DBG)
+ ALOGI("makeIPAHAL(%d, %s)", version,
+ (mgr != nullptr) ? "provided" : "null");
+ if (nullptr == mgr) return NULL;
+ else if (version != 1) return NULL;
+ HAL* ret = new HAL(mgr);
+ if (nullptr == ret) return NULL;
+ configureRpcThreadpool(1, false);
+ ret->registerAsSystemService("ipacm");
+ return ret;
+} /* makeIPAHAL */
+
+
+/* ------------------------------ PRIVATE ----------------------------------- */
+HAL::HAL(IOffloadManager* mgr) : mLogs("HAL Function Calls", 50) {
+ mIPA = mgr;
+ mCb.clear();
+ mCbIpa = nullptr;
+ mCbCt = nullptr;
+} /* HAL */
+
+void HAL::registerAsSystemService(const char* name) {
+ status_t ret = 0;
+
+ ret = IOffloadControl::registerAsService(name);
+ if (ret != 0) ALOGE("Failed to register IOffloadControl (%d)", ret);
+ else if (DBG) {
+ ALOGI("Successfully registered IOffloadControl (%s)", name);
+ }
+
+ IOffloadConfig::registerAsService(name);
+ if (ret != 0) ALOGE("Failed to register IOffloadConfig (%d)", ret);
+ else if (DBG) {
+ ALOGI("Successfully registered IOffloadConfig (%s)", name);
+ }
+} /* registerAsSystemService */
+
+void HAL::doLogcatDump() {
+ ALOGD("mHandles");
+ ALOGD("========");
+ /* @TODO This will segfault if they aren't initialized and I don't currently
+ * care to check for initialization in a function that isn't used anyways
+ * ALOGD("fd1->%d", mHandle1->data[0]);
+ * ALOGD("fd2->%d", mHandle2->data[0]);
+ */
+ ALOGD("========");
+} /* doLogcatDump */
+
+HAL::BoolResult HAL::makeInputCheckFailure(string customErr) {
+ BoolResult ret;
+ ret.success = false;
+ ret.errMsg = "Failed Input Checks: " + customErr;
+ return ret;
+} /* makeInputCheckFailure */
+
+HAL::BoolResult HAL::ipaResultToBoolResult(RET in) {
+ BoolResult ret;
+ ret.success = (in >= RET::SUCCESS);
+ switch (in) {
+ case RET::FAIL_TOO_MANY_PREFIXES:
+ ret.errMsg = "Too Many Prefixes Provided";
+ break;
+ case RET::FAIL_UNSUPPORTED:
+ ret.errMsg = "Unsupported by Hardware";
+ break;
+ case RET::FAIL_INPUT_CHECK:
+ ret.errMsg = "Failed Input Checks";
+ break;
+ case RET::FAIL_HARDWARE:
+ ret.errMsg = "Hardware did not accept";
+ break;
+ case RET::FAIL_TRY_AGAIN:
+ ret.errMsg = "Try Again";
+ break;
+ case RET::SUCCESS:
+ ret.errMsg = "Successful";
+ break;
+ case RET::SUCCESS_DUPLICATE_CONFIG:
+ ret.errMsg = "Successful: Was a duplicate configuration";
+ break;
+ case RET::SUCCESS_NO_OP:
+ ret.errMsg = "Successful: No action needed";
+ break;
+ case RET::SUCCESS_OPTIMIZED:
+ ret.errMsg = "Successful: Performed optimized version of action";
+ break;
+ default:
+ ret.errMsg = "Unknown Error";
+ break;
+ }
+ return ret;
+} /* ipaResultToBoolResult */
+
+/* This will likely always result in doubling the number of loops the execution
+ * goes through. Obviously that is suboptimal. But if we first translate
+ * away from all HIDL specific code, then we can avoid sprinkling HIDL
+ * dependencies everywhere.
+ */
+vector<string> HAL::convertHidlStrToStdStr(hidl_vec<hidl_string> in) {
+ vector<string> ret;
+ for (size_t i = 0; i < in.size(); i++) {
+ string add = in[i];
+ ret.push_back(add);
+ }
+ return ret;
+} /* convertHidlStrToStdStr */
+
+void HAL::registerEventListeners() {
+ registerIpaCb();
+ registerCtCb();
+} /* registerEventListeners */
+
+void HAL::registerIpaCb() {
+ if (isInitialized() && mCbIpa == nullptr) {
+ LocalLogBuffer::FunctionLog fl("registerEventListener");
+ mCbIpa = new IpaEventRelay(mCb);
+ mIPA->registerEventListener(mCbIpa);
+ mLogs.addLog(fl);
+ } else {
+ ALOGE("Failed to registerIpaCb (isInitialized()=%s, (mCbIpa == nullptr)=%s)",
+ isInitialized() ? "true" : "false",
+ (mCbIpa == nullptr) ? "true" : "false");
+ }
+} /* registerIpaCb */
+
+void HAL::registerCtCb() {
+ if (isInitialized() && mCbCt == nullptr) {
+ LocalLogBuffer::FunctionLog fl("registerCtTimeoutUpdater");
+ mCbCt = new CtUpdateAmbassador(mCb);
+ mIPA->registerCtTimeoutUpdater(mCbCt);
+ mLogs.addLog(fl);
+ } else {
+ ALOGE("Failed to registerCtCb (isInitialized()=%s, (mCbCt == nullptr)=%s)",
+ isInitialized() ? "true" : "false",
+ (mCbCt == nullptr) ? "true" : "false");
+ }
+} /* registerCtCb */
+
+void HAL::unregisterEventListeners() {
+ unregisterIpaCb();
+ unregisterCtCb();
+} /* unregisterEventListeners */
+
+void HAL::unregisterIpaCb() {
+ if (mCbIpa != nullptr) {
+ LocalLogBuffer::FunctionLog fl("unregisterEventListener");
+ mIPA->unregisterEventListener(mCbIpa);
+ mCbIpa = nullptr;
+ mLogs.addLog(fl);
+ } else {
+ ALOGE("Failed to unregisterIpaCb");
+ }
+} /* unregisterIpaCb */
+
+void HAL::unregisterCtCb() {
+ if (mCbCt != nullptr) {
+ LocalLogBuffer::FunctionLog fl("unregisterCtTimeoutUpdater");
+ mIPA->unregisterCtTimeoutUpdater(mCbCt);
+ mCbCt = nullptr;
+ mLogs.addLog(fl);
+ } else {
+ ALOGE("Failed to unregisterCtCb");
+ }
+} /* unregisterCtCb */
+
+void HAL::clearHandles() {
+ ALOGI("clearHandles()");
+ /* @TODO handle this more gracefully... also remove the log
+ *
+ * Things that would be nice, but I can't do:
+ * [1] Destroy the object (it's on the stack)
+ * [2] Call freeHandle (it's private)
+ *
+ * Things I can do but are hacks:
+ * [1] Look at code and notice that setTo immediately calls freeHandle
+ */
+ mHandle1.setTo(nullptr, true);
+ mHandle2.setTo(nullptr, true);
+} /* clearHandles */
+
+bool HAL::isInitialized() {
+ return mCb.get() != nullptr;
+} /* isInitialized */
+
+
+/* -------------------------- IOffloadConfig -------------------------------- */
+Return<void> HAL::setHandles(
+ const hidl_handle &fd1,
+ const hidl_handle &fd2,
+ setHandles_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+
+ if (fd1->numFds != 1) {
+ BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd1)");
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+
+ mLogs.addLog(fl);
+ return Void();
+ }
+
+ if (fd2->numFds != 1) {
+ BoolResult res = makeInputCheckFailure("Must provide exactly one FD per handle (fd2)");
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+
+ mLogs.addLog(fl);
+ return Void();
+ }
+
+ /* The = operator calls freeHandle internally. Therefore, if we were using
+ * these handles previously, they're now gone... forever. But hopefully the
+ * new ones kick in very quickly.
+ *
+ * After freeing anything previously held, it will dup the FD so we have our
+ * own copy.
+ */
+ mHandle1 = fd1;
+ mHandle2 = fd2;
+
+ /* Log the DUPed FD instead of the actual input FD so that we can lookup
+ * this value in ls -l /proc/<pid>/<fd>
+ */
+ fl.addArg("fd1", mHandle1->data[0]);
+ fl.addArg("fd2", mHandle2->data[0]);
+
+ /* Try to provide each handle to IPACM. Destroy our DUPed hidl_handles if
+ * IPACM does not like either input. This keeps us from leaking FDs or
+ * providing half solutions.
+ *
+ * @TODO unfortunately, this does not cover duplicate configs where IPACM
+ * thinks it is still holding on to a handle that we would have freed above.
+ * It also probably means that IPACM would not know about the first FD being
+ * freed if it rejects the second FD.
+ */
+ RET ipaReturn = mIPA->provideFd(mHandle1->data[0], UDP_SUBSCRIPTIONS);
+ if (ipaReturn == RET::SUCCESS) {
+ ipaReturn = mIPA->provideFd(mHandle2->data[0], TCP_SUBSCRIPTIONS);
+ }
+
+ if (ipaReturn != RET::SUCCESS) {
+ ALOGE("IPACM failed to accept the FDs (%d %d)", mHandle1->data[0],
+ mHandle2->data[0]);
+ clearHandles();
+ } else {
+ /* @TODO remove logs after stabilization */
+ ALOGI("IPACM was provided two FDs (%d, %d)", mHandle1->data[0],
+ mHandle2->data[0]);
+ }
+
+ BoolResult res = ipaResultToBoolResult(ipaReturn);
+ hidl_cb(res.success, res.errMsg);
+
+ fl.setResult(res.success, res.errMsg);
+ mLogs.addLog(fl);
+ return Void();
+} /* setHandles */
+
+
+/* -------------------------- IOffloadControl ------------------------------- */
+Return<void> HAL::initOffload
+(
+ const ::android::sp<ITetheringOffloadCallback>& cb,
+ initOffload_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+
+ if (isInitialized()) {
+ BoolResult res = makeInputCheckFailure("Already initialized");
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ mLogs.addLog(fl);
+ } else {
+ /* Should storing the CB be a function? */
+ mCb = cb;
+ registerEventListeners();
+ BoolResult res = ipaResultToBoolResult(RET::SUCCESS);
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ mLogs.addLog(fl);
+ }
+
+ return Void();
+} /* initOffload */
+
+Return<void> HAL::stopOffload
+(
+ stopOffload_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+
+ if (!isInitialized()) {
+ BoolResult res = makeInputCheckFailure("Was never initialized");
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ mLogs.addLog(fl);
+ } else {
+ /* Should removing the CB be a function? */
+ mCb.clear();
+ unregisterEventListeners();
+
+ RET ipaReturn = mIPA->stopAllOffload();
+ if (ipaReturn != RET::SUCCESS) {
+ /* Ignore IPAs return value here and provide why stopAllOffload
+ * failed. However, if IPA failed to clearAllFds, then we can't
+ * clear our map because they may still be in use.
+ */
+ RET ret = mIPA->clearAllFds();
+ if (ret == RET::SUCCESS) {
+ clearHandles();
+ }
+ } else {
+ ipaReturn = mIPA->clearAllFds();
+ /* If IPA fails, they may still be using these for some reason. */
+ if (ipaReturn == RET::SUCCESS) {
+ clearHandles();
+ } else {
+ ALOGE("IPACM failed to return success for clearAllFds so they will not be released...");
+ }
+ }
+
+ BoolResult res = ipaResultToBoolResult(ipaReturn);
+ hidl_cb(res.success, res.errMsg);
+
+ fl.setResult(res.success, res.errMsg);
+ mLogs.addLog(fl);
+ }
+
+ return Void();
+} /* stopOffload */
+
+Return<void> HAL::setLocalPrefixes
+(
+ const hidl_vec<hidl_string>& prefixes,
+ setLocalPrefixes_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+ fl.addArg("prefixes", "unused");
+ #pragma unused(prefixes)
+
+ /* Fake Success */
+ BoolResult res = ipaResultToBoolResult(RET::SUCCESS);
+ hidl_cb(res.success, res.errMsg);
+
+ fl.setResult(res.success, res.errMsg);
+ return Void();
+} /* setLocalPrefixes */
+
+Return<void> HAL::getForwardedStats
+(
+ const hidl_string& upstream,
+ getForwardedStats_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+ fl.addArg("upstream", upstream);
+
+ OffloadStatistics ret;
+ RET ipaReturn = mIPA->getStats(upstream.c_str(), true, ret);
+ if (ipaReturn == RET::SUCCESS) {
+ hidl_cb(ret.getTotalRxBytes(), ret.getTotalTxBytes());
+ fl.setResult(ret.getTotalRxBytes(), ret.getTotalTxBytes());
+ } else {
+ /* @TODO Ensure the output is zeroed, but this is probably not enough to
+ * tell Framework that an error has occurred. If, for example, they had
+ * not yet polled for statistics previously, they may incorrectly assume
+ * that simply no statistics have transpired on hardware path.
+ *
+ * Maybe ITetheringOffloadCallback:onEvent(OFFLOAD_STOPPED_ERROR) is
+ * enough to handle this case, time will tell.
+ */
+ hidl_cb(0, 0);
+ fl.setResult(0, 0);
+ }
+
+ mLogs.addLog(fl);
+ return Void();
+} /* getForwardedStats */
+
+Return<void> HAL::setDataLimit
+(
+ const hidl_string& upstream,
+ uint64_t limit,
+ setDataLimit_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+ fl.addArg("upstream", upstream);
+ fl.addArg("limit", limit);
+
+ RET ipaReturn = mIPA->setQuota(upstream.c_str(), limit);
+ BoolResult res = ipaResultToBoolResult(ipaReturn);
+ hidl_cb(res.success, res.errMsg);
+
+ fl.setResult(res.success, res.errMsg);
+ mLogs.addLog(fl);
+ return Void();
+} /* setDataLimit */
+
+Return<void> HAL::setUpstreamParameters
+(
+ const hidl_string& iface,
+ const hidl_string& v4Addr,
+ const hidl_string& v4Gw,
+ const hidl_vec<hidl_string>& v6Gws,
+ setUpstreamParameters_cb hidl_cb
+) {
+ vector<string> v6GwStrs = convertHidlStrToStdStr(v6Gws);
+
+ LocalLogBuffer::FunctionLog fl(__func__);
+ fl.addArg("iface", iface);
+ fl.addArg("v4Addr", v4Addr);
+ fl.addArg("v4Gw", v4Gw);
+ fl.addArg("v6Gws", v6GwStrs);
+
+ PrefixParser v4AddrParser;
+ PrefixParser v4GwParser;
+ PrefixParser v6GwParser;
+
+ /* @TODO maybe we should enforce that these addresses and gateways are fully
+ * qualified here. But then, how do we allow them to be empty/null as well
+ * while still preserving a sane API on PrefixParser?
+ */
+ if (!v4AddrParser.addV4(v4Addr) && !v4Addr.empty()) {
+ BoolResult res = makeInputCheckFailure(v4AddrParser.getLastErrAsStr());
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ } else if (!v4GwParser.addV4(v4Gw) && !v4Gw.empty()) {
+ BoolResult res = makeInputCheckFailure(v4GwParser.getLastErrAsStr());
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ } else if (v6GwStrs.size() >= 1 && !v6GwParser.addV6(v6GwStrs)) {
+ BoolResult res = makeInputCheckFailure(v6GwParser.getLastErrAsStr());
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ } else if (v6GwParser.size() > 1) {
+ RET ipaReturn = mIPA->stopAllOffload();
+ if (ipaReturn != RET::SUCCESS) {
+ BoolResult res =
+ makeInputCheckFailure("Cannot accept more than 1 IPv6 Gateway. Offload still running and may result in data path errors");
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ } else {
+ BoolResult res =
+ makeInputCheckFailure("Cannot accept more than 1 IPv6 Gateway. In an effort to avoid any data path errors, offload has been stopped");
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ }
+ } else {
+ RET ipaReturn = mIPA->setUpstream(
+ iface.c_str(),
+ v4GwParser.getFirstPrefix(),
+ v6GwParser.getFirstPrefix());
+ BoolResult res = ipaResultToBoolResult(ipaReturn);
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ }
+
+ mLogs.addLog(fl);
+ return Void();
+} /* setUpstreamParameters */
+
+Return<void> HAL::addDownstream
+(
+ const hidl_string& iface,
+ const hidl_string& prefix,
+ addDownstream_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+ fl.addArg("iface", iface);
+ fl.addArg("prefix", prefix);
+
+ PrefixParser prefixParser;
+
+ if (!prefixParser.add(prefix)) {
+ BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr());
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ } else {
+ RET ipaReturn = mIPA->addDownstream(
+ iface.c_str(),
+ prefixParser.getFirstPrefix());
+ BoolResult res = ipaResultToBoolResult(ipaReturn);
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ }
+
+ mLogs.addLog(fl);
+ return Void();
+} /* addDownstream */
+
+Return<void> HAL::removeDownstream
+(
+ const hidl_string& iface,
+ const hidl_string& prefix,
+ removeDownstream_cb hidl_cb
+) {
+ LocalLogBuffer::FunctionLog fl(__func__);
+ fl.addArg("iface", iface);
+ fl.addArg("prefix", prefix);
+
+ PrefixParser prefixParser;
+
+ if (!prefixParser.add(prefix)) {
+ BoolResult res = makeInputCheckFailure(prefixParser.getLastErrAsStr());
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ } else {
+ RET ipaReturn = mIPA->removeDownstream(
+ iface.c_str(),
+ prefixParser.getFirstPrefix());
+ BoolResult res = ipaResultToBoolResult(ipaReturn);
+ hidl_cb(res.success, res.errMsg);
+ fl.setResult(res.success, res.errMsg);
+ }
+
+ mLogs.addLog(fl);
+ return Void();
+} /* removeDownstream */
diff --git a/msm8998/hal/src/IpaEventRelay.cpp b/msm8998/hal/src/IpaEventRelay.cpp
new file mode 100644
index 0000000..788b152
--- /dev/null
+++ b/msm8998/hal/src/IpaEventRelay.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "IPAHALService/IpaEventRelay"
+/* External Includes */
+#include <cutils/log.h>
+
+/* HIDL Includes */
+#include <android/hardware/tetheroffload/control/1.0/ITetheringOffloadCallback.h>
+
+/* Internal Includes */
+#include "IpaEventRelay.h"
+
+/* Namespace pollution avoidance */
+using ::android::hardware::tetheroffload::control::V1_0::ITetheringOffloadCallback;
+using ::android::hardware::tetheroffload::control::V1_0::OffloadCallbackEvent;
+
+
+IpaEventRelay::IpaEventRelay(
+ const ::android::sp<ITetheringOffloadCallback>& cb) : mFramework(cb) {
+} /* IpaEventRelay */
+
+void IpaEventRelay::onOffloadStarted() {
+ ALOGI("onOffloadStarted()");
+ mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STARTED);
+} /* onOffloadStarted */
+
+void IpaEventRelay::onOffloadStopped(StoppedReason reason) {
+ ALOGI("onOffloadStopped(%d)", reason);
+ switch (reason) {
+ case REQUESTED:
+ /*
+ * No way to communicate this to Framework right now, they make an
+ * assumption that offload is stopped when they remove the
+ * configuration.
+ */
+ break;
+ case ERROR:
+ mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STOPPED_ERROR);
+ break;
+ case UNSUPPORTED:
+ mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STOPPED_UNSUPPORTED);
+ break;
+ default:
+ ALOGE("Unknown stopped reason(%d)", reason);
+ break;
+ }
+} /* onOffloadStopped */
+
+void IpaEventRelay::onOffloadSupportAvailable() {
+ ALOGI("onOffloadSupportAvailable()");
+ mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_SUPPORT_AVAILABLE);
+} /* onOffloadSupportAvailable */
+
+void IpaEventRelay::onLimitReached() {
+ ALOGI("onLimitReached()");
+ mFramework->onEvent(OffloadCallbackEvent::OFFLOAD_STOPPED_LIMIT_REACHED);
+} /* onLimitReached */
diff --git a/msm8998/hal/src/LocalLogBuffer.cpp b/msm8998/hal/src/LocalLogBuffer.cpp
new file mode 100644
index 0000000..f556e40
--- /dev/null
+++ b/msm8998/hal/src/LocalLogBuffer.cpp
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#define LOG_TAG "IPAHALService/dump"
+
+/* External Includes */
+#include <cutils/log.h>
+#include <deque>
+#include <string>
+#include <sys/types.h>
+#include <vector>
+
+/* Internal Includes */
+#include "LocalLogBuffer.h"
+
+/* Namespace pollution avoidance */
+using ::std::deque;
+using ::std::string;
+using ::std::vector;
+
+
+LocalLogBuffer::FunctionLog::FunctionLog(string funcName) : mName(funcName) {
+ mArgsProvided = false;
+} /* FunctionLog */
+
+LocalLogBuffer::FunctionLog::FunctionLog(const FunctionLog& other) :
+ mName(other.mName) {
+ mArgsProvided = other.mArgsProvided;
+ /* Is this right? How do you copy stringstreams without wizardry? */
+ mSSArgs.str(other.mSSArgs.str());
+ mSSReturn.str(other.mSSReturn.str());
+} /* FunctionLog */
+
+void LocalLogBuffer::FunctionLog::addArg(string kw, string arg) {
+ maybeAddArgsComma();
+ mSSArgs << kw << "=" << arg;
+} /* addArg */
+
+void LocalLogBuffer::FunctionLog::addArg(string kw, vector<string> args) {
+ maybeAddArgsComma();
+ mSSArgs << kw << "=[";
+ for (size_t i = 0; i < args.size(); i++) {
+ mSSArgs << args[i];
+ if (i < (args.size() - 1))
+ mSSArgs << ", ";
+ }
+ mSSArgs << "]";
+} /* addArg */
+
+void LocalLogBuffer::FunctionLog::addArg(string kw, uint64_t arg) {
+ maybeAddArgsComma();
+ mSSArgs << kw << "=" << arg;
+} /* addArg */
+
+void LocalLogBuffer::FunctionLog::maybeAddArgsComma() {
+ if (!mArgsProvided) {
+ mArgsProvided = true;
+ } else {
+ mSSArgs << ", ";
+ }
+} /* maybeAddArgsComma */
+
+void LocalLogBuffer::FunctionLog::setResult(bool success, string msg) {
+ mSSReturn << "[" << ((success) ? "success" : "failure") << ", " << msg
+ << "]";
+} /* setResult */
+
+void LocalLogBuffer::FunctionLog::setResult(vector<unsigned int> ret) {
+ mSSReturn << "[";
+ for (size_t i = 0; i < ret.size(); i++) {
+ mSSReturn << ret[i];
+ if (i < (ret.size() - 1))
+ mSSReturn << ", ";
+ }
+ mSSReturn << "]";
+} /* setResult */
+
+void LocalLogBuffer::FunctionLog::setResult(uint64_t rx, uint64_t tx) {
+ mSSReturn << "[rx=" << rx << ", tx=" << tx << "]";
+} /* setResult */
+
+string LocalLogBuffer::FunctionLog::toString() {
+ stringstream ret;
+ ret << mName << "(" << mSSArgs.str() << ") returned " << mSSReturn.str();
+ return ret.str();
+} /* toString */
+
+LocalLogBuffer::LocalLogBuffer(string name, int maxLogs) : mName(name),
+ mMaxLogs(maxLogs) {
+} /* LocalLogBuffer */
+
+void LocalLogBuffer::addLog(FunctionLog log) {
+ while (mLogs.size() > mMaxLogs)
+ mLogs.pop_front();
+ mLogs.push_back(log);
+} /* addLog */
+
+void LocalLogBuffer::toLogcat() {
+ for (size_t i = 0; i < mLogs.size(); i++)
+ ALOGD("%s: %s", mName.c_str(), mLogs[i].toString().c_str());
+} /* toLogcat */
diff --git a/msm8998/hal/src/OffloadStatistics.cpp b/msm8998/hal/src/OffloadStatistics.cpp
new file mode 100644
index 0000000..8f8beb6
--- /dev/null
+++ b/msm8998/hal/src/OffloadStatistics.cpp
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <string.h>
+#include <sys/types.h>
+
+#include "OffloadStatistics.h"
+
+
+/* ------------------------------ PUBLIC ------------------------------------ */
+OffloadStatistics::OffloadStatistics() {
+ this->upstream = "UNSET";
+ this->rx = 0;
+ this->tx = 0;
+} /* OffloadStatistics */
+
+OffloadStatistics::OffloadStatistics
+(
+ std::string upstream
+) {
+ this->upstream = upstream;
+ this->rx = 0;
+ this->tx =0;
+} /* OffloadStatistics */
+
+uint64_t OffloadStatistics::getTotalRxBytes() {
+ return rx;
+} /* getTotalRxBytes */
+
+uint64_t OffloadStatistics::getTotalTxBytes() {
+ return tx;
+} /* getTotalTxBytes */
diff --git a/msm8998/hal/src/PrefixParser.cpp b/msm8998/hal/src/PrefixParser.cpp
new file mode 100644
index 0000000..60aae08
--- /dev/null
+++ b/msm8998/hal/src/PrefixParser.cpp
@@ -0,0 +1,375 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+/* External Includes */
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <vector>
+
+/* Internal Includes */
+#include "IOffloadManager.h"
+#include "PrefixParser.h"
+
+/* Avoiding namespace pollution */
+using IP_FAM = ::IOffloadManager::IP_FAM;
+using Prefix = ::IOffloadManager::Prefix;
+
+using ::std::string;
+using ::std::vector;
+
+
+/* ------------------------------ PUBLIC ------------------------------------ */
+PrefixParser::PrefixParser() {
+ mLastErr = "No Err";
+} /* PrefixParser */
+
+bool PrefixParser::add(vector<string> in) {
+ return add(in, IP_FAM::INVALID);
+} /* add */
+
+bool PrefixParser::add(string in) {
+ return add(in, IP_FAM::INVALID);
+} /* add */
+
+bool PrefixParser::addV4(string in) {
+ return add(in, IP_FAM::V4);
+} /* addV4 */
+
+bool PrefixParser::addV4(vector<string> in) {
+ return add(in, IP_FAM::V4);
+} /* addV4 */
+
+bool PrefixParser::addV6(string in) {
+ return add(in, IP_FAM::V6);
+} /* addV6 */
+
+bool PrefixParser::addV6(vector<string> in) {
+ for (size_t i = 0; i < in.size(); i++) {
+ if (!addV6(in[i]))
+ return false;
+ }
+ return true;
+} /* addV6 */
+
+int PrefixParser::size() {
+ return mPrefixes.size();
+} /* size */
+
+bool PrefixParser::allAreFullyQualified() {
+ for (size_t i = 0; i < mPrefixes.size(); i++) {
+ if (mPrefixes[i].fam == IP_FAM::V4) {
+ uint32_t masked = mPrefixes[i].v4Addr & mPrefixes[i].v4Mask;
+ if (masked != mPrefixes[i].v4Addr)
+ return false;
+ } else {
+ uint32_t masked[4];
+ masked[0] = mPrefixes[i].v6Addr[0] & mPrefixes[i].v6Mask[0];
+ masked[1] = mPrefixes[i].v6Addr[1] & mPrefixes[i].v6Mask[1];
+ masked[2] = mPrefixes[i].v6Addr[2] & mPrefixes[i].v6Mask[2];
+ masked[3] = mPrefixes[i].v6Addr[3] & mPrefixes[i].v6Mask[3];
+ for (int j = 0; j < 4; j++) {
+ if (masked[j] != mPrefixes[i].v6Addr[j])
+ return false;
+ }
+ }
+ }
+ return true;
+} /* allAreFullyQualified */
+
+Prefix PrefixParser::getFirstPrefix() {
+ if (size() >= 1)
+ return mPrefixes[0];
+ return makeBlankPrefix(IP_FAM::INVALID);
+} /* getFirstPrefix */
+
+string PrefixParser::getLastErrAsStr() {
+ return mLastErr;
+} /* getLastErrAsStr */
+
+
+/* ------------------------------ PRIVATE ----------------------------------- */
+bool PrefixParser::add(vector<string> in, IP_FAM famHint) {
+ for (size_t i = 0; i < in.size(); i++) {
+ if (!add(in[i], famHint))
+ return false;
+ }
+ return true;
+} /* add */
+
+bool PrefixParser::add(string in, IP_FAM famHint) {
+ if (famHint == IP_FAM::INVALID)
+ famHint = guessIPFamily(in);
+
+ string subnet;
+ string addr;
+
+ if (!splitIntoAddrAndMask(in, addr, subnet)) {
+ mLastErr = "Failed to split into Address and Mask(" + in + ")";
+ return false;
+ }
+
+ int mask = parseSubnetMask(subnet, famHint);
+ if (!isMaskValid(mask, famHint))
+ return false;
+
+ Prefix pre = makeBlankPrefix(famHint);
+
+ if (famHint == IP_FAM::V4) {
+ if (!parseV4Addr(addr, pre)) {
+ mLastErr = "Failed to parse V4 Address(" + addr + ")";
+ return false;
+ }
+ } else if (!parseV6Addr(addr, pre)) {
+ mLastErr = "Failed to parse V6 Address(" + addr + ")";
+ return false;
+ }
+
+ if (famHint == IP_FAM::V4 && !populateV4Mask(mask, pre)) {
+ mLastErr = "Failed to populate IPv4 Mask(" + std::to_string(mask)
+ + ", " + addr + ")";
+ return false;
+ } else if (!populateV6Mask(mask, pre)) {
+ mLastErr = "Failed to populate IPv6 Mask(" + std::to_string(mask)
+ + ", " + addr + ")";
+ return false;
+ }
+
+ mPrefixes.push_back(pre);
+ return true;
+} /* add */
+
+/* Assumption (based on man inet_pton)
+ *
+ * X represents a hex character
+ * d represents a base 10 digit
+ * / represents the start of the subnet mask
+ * (assume that it can be left off of all below combinations)
+ *
+ * IPv4 Addresses always look like the following:
+ * ddd.ddd.ddd.ddd/dd
+ *
+ * IPv6 Addresses can look a few different ways:
+ * x:x:x:x:x:x:x:x/ddd
+ * x::x/ddd
+ * x:x:x:x:x:x:d.d.d.d/ddd
+ *
+ * Therefore, if a presentation of an IP Address contains a colon, then it
+ * may not be a valid IPv6, but, it is definitely not valid IPv4. If a
+ * presentation of an IP Address does not contain a colon, then it may not be
+ * a valid IPv4, but, it is definitely not IPv6.
+ */
+IP_FAM PrefixParser::guessIPFamily(string in) {
+ size_t found = in.find(":");
+ if (found != string::npos)
+ return IP_FAM::V6;
+ return IP_FAM::V4;
+} /* guessIPFamily */
+
+bool PrefixParser::splitIntoAddrAndMask(string in, string &addr, string &mask) {
+ size_t pos = in.find("/");
+
+ if (pos != string::npos && pos >= 1) {
+ /* addr is now everything up until the first / */
+ addr = in.substr(0, pos);
+ } else if (pos == string::npos) {
+ /* There is no /, so the entire input is an address */
+ addr = in;
+ } else {
+ /* There was nothing before the /, not recoverable */
+ return false;
+ }
+
+ if (pos != string::npos && pos < in.size()) {
+ /* There is a / and it is not the last character. Everything after /
+ * must be the subnet.
+ */
+ mask = in.substr(pos + 1);
+ } else if (pos != string::npos && pos == in.size()) {
+ /* There is a /, but it is the last character. This is garbage, but,
+ * we may still be able to interpret the address so we will throw it
+ * out.
+ */
+ mask = "";
+ } else if (pos == string::npos) {
+ /* There is no /, therefore, there is no subnet */
+ mask = "";
+ } else {
+ /* This really shouldn't be possible because it would imply that find
+ * returned a position larger than the size of the input. Just
+ * preserving sanity that mask is always initialized.
+ */
+ mask = "";
+ }
+
+ return true;
+} /* splitIntoAddrAndMask */
+
+int PrefixParser::parseSubnetMask(string in, IP_FAM famHint) {
+ if (in.empty())
+ /* Treat no subnet mask as fully qualified */
+ return (famHint == IP_FAM::V6) ? 128 : 32;
+ return atoi(in.c_str());
+} /* parseSubnetMask */
+
+bool PrefixParser::parseV4Addr(string in, Prefix &out) {
+ struct sockaddr_in sa;
+
+ int ret = inet_pton(AF_INET, in.c_str(), &(sa.sin_addr));
+
+ if (ret < 0) {
+ /* errno would be valid */
+ return false;
+ } else if (ret == 0) {
+ /* input was not a valid IP address */
+ return false;
+ }
+
+ /* Address in network byte order */
+ out.v4Addr = htonl(sa.sin_addr.s_addr);
+ return true;
+} /* parseV4Addr */
+
+bool PrefixParser::parseV6Addr(string in, Prefix &out) {
+ struct sockaddr_in6 sa;
+
+ int ret = inet_pton(AF_INET6, in.c_str(), &(sa.sin6_addr));
+
+ if (ret < 0) {
+ /* errno would be valid */
+ return false;
+ } else if (ret == 0) {
+ /* input was not a valid IP address */
+ return false;
+ }
+
+ /* Translate unsigned chars to unsigned ints to match IPA
+ *
+ * TODO there must be a better way to do this beyond bit fiddling
+ * Maybe a Union since we've already made the assumption that the data
+ * structures match?
+ */
+ out.v6Addr[0] = (sa.sin6_addr.s6_addr[0] << 24) |
+ (sa.sin6_addr.s6_addr[1] << 16) |
+ (sa.sin6_addr.s6_addr[2] << 8) |
+ (sa.sin6_addr.s6_addr[3]);
+ out.v6Addr[1] = (sa.sin6_addr.s6_addr[4] << 24) |
+ (sa.sin6_addr.s6_addr[5] << 16) |
+ (sa.sin6_addr.s6_addr[6] << 8) |
+ (sa.sin6_addr.s6_addr[7]);
+ out.v6Addr[2] = (sa.sin6_addr.s6_addr[8] << 24) |
+ (sa.sin6_addr.s6_addr[9] << 16) |
+ (sa.sin6_addr.s6_addr[10] << 8) |
+ (sa.sin6_addr.s6_addr[11]);
+ out.v6Addr[3] = (sa.sin6_addr.s6_addr[12] << 24) |
+ (sa.sin6_addr.s6_addr[13] << 16) |
+ (sa.sin6_addr.s6_addr[14] << 8) |
+ (sa.sin6_addr.s6_addr[15]);
+ return true;
+} /* parseV6Addr */
+
+bool PrefixParser::populateV4Mask(int mask, Prefix &out) {
+ if (mask < 0 || mask > 32)
+ return false;
+ out.v4Mask = createMask(mask);
+ return true;
+} /* populateV4Mask */
+
+bool PrefixParser::populateV6Mask(int mask, Prefix &out) {
+ if (mask < 0 || mask > 128)
+ return false;
+
+ for (int i = 0; i < 4; i++) {
+ out.v6Mask[i] = createMask(mask);
+ mask = (mask > 32) ? mask - 32 : 0;
+ }
+
+ return true;
+} /* populateV6Mask */
+
+uint32_t PrefixParser::createMask(int mask) {
+ uint32_t ret = 0;
+
+ if (mask >= 32) {
+ ret = ~ret;
+ return ret;
+ }
+
+ for (int i = 0; i < 32; i++) {
+ if (i < mask)
+ ret = (ret << 1) | 1;
+ else
+ ret = (ret << 1);
+ }
+
+ return ret;
+} /* createMask */
+
+Prefix PrefixParser::makeBlankPrefix(IP_FAM famHint) {
+ Prefix ret;
+
+ ret.fam = famHint;
+
+ ret.v4Addr = 0;
+ ret.v4Mask = 0;
+
+ ret.v6Addr[0] = 0;
+ ret.v6Addr[1] = 0;
+ ret.v6Addr[2] = 0;
+ ret.v6Addr[3] = 0;
+
+ ret.v6Mask[0] = 0;
+ ret.v6Mask[1] = 0;
+ ret.v6Mask[2] = 0;
+ ret.v6Mask[3] = 0;
+
+ return ret;
+} /* makeBlankPrefix */
+
+bool PrefixParser::isMaskValid(int mask, IP_FAM fam) {
+ if (mask < 0) {
+ mLastErr = "Failed parse subnet mask(" + std::to_string(mask) + ")";
+ return false;
+ } else if (mask == 0) {
+ mLastErr = "Subnet mask cannot be 0(" + std::to_string(mask) + ")";
+ return false;
+ } else if (fam == IP_FAM::V4 && mask > 32) {
+ mLastErr = "Interpreted address as V4 but mask was too large("
+ + std::to_string(mask) + ")";
+ return false;
+ } else if (fam == IP_FAM::V6 && mask > 128) {
+ mLastErr = "Interpreted address as V6 but mask was too large("
+ + std::to_string(mask) + ")";
+ return false;
+ }
+
+ return true;
+} /* isMaskValid */
diff --git a/msm8998/ipacm/inc/IPACM_ConntrackClient.h b/msm8998/ipacm/inc/IPACM_ConntrackClient.h
index a6076cf..16d5b9c 100644
--- a/msm8998/ipacm/inc/IPACM_ConntrackClient.h
+++ b/msm8998/ipacm/inc/IPACM_ConntrackClient.h
@@ -91,6 +91,13 @@ public:
static IPACM_ConntrackClient* GetInstance();
+ static void UNRegisterWithConnTrack(void);
+ int fd_tcp;
+ int fd_udp;
+
+ unsigned int subscrips_tcp;
+ unsigned int subscrips_udp;
+
#ifdef IPACM_DEBUG
#define iptodot(X,Y) \
IPACMLOG(" %s(0x%x): %d.%d.%d.%d\n", X, Y, ((Y>>24) & 0xFF), ((Y>>16) & 0xFF), ((Y>>8) & 0xFF), (Y & 0xFF));
diff --git a/msm8998/ipacm/inc/IPACM_ConntrackListener.h b/msm8998/ipacm/inc/IPACM_ConntrackListener.h
index cdf3ef5..d965cf7 100644
--- a/msm8998/ipacm/inc/IPACM_ConntrackListener.h
+++ b/msm8998/ipacm/inc/IPACM_ConntrackListener.h
@@ -87,7 +87,6 @@ private:
void TriggerWANUp(void *);
void TriggerWANDown(uint32_t);
int CreateNatThreads(void);
- int CreateConnTrackThreads(void);
bool AddIface(nat_table_entry *, bool *);
void AddORDeleteNatEntry(const nat_entry_bundle *);
void PopulateTCPorUDPEntry(struct nf_conntrack *, uint32_t, nat_table_entry *);
@@ -116,6 +115,7 @@ public:
void HandleNeighIpAddrDelEvt(uint32_t);
void HandleSTAClientAddEvt(uint32_t);
void HandleSTAClientDelEvt(uint32_t);
+ int CreateConnTrackThreads(void);
};
extern IPACM_ConntrackListener *CtList;
diff --git a/msm8998/ipacm/inc/IPACM_Defs.h b/msm8998/ipacm/inc/IPACM_Defs.h
index d2cc362..74ed3bf 100644
--- a/msm8998/ipacm/inc/IPACM_Defs.h
+++ b/msm8998/ipacm/inc/IPACM_Defs.h
@@ -185,6 +185,8 @@ typedef enum
IPA_ETH_BRIDGE_CLIENT_DEL, /* ipacm_event_eth_bridge*/
IPA_ETH_BRIDGE_WLAN_SCC_MCC_SWITCH, /* ipacm_event_eth_bridge*/
IPA_LAN_DELETE_SELF, /* ipacm_event_data_fid */
+ IPA_DOWNSTREAM_ADD, /* ipacm_event_ipahal_stream */
+ IPA_DOWNSTREAM_DEL, /* ipacm_event_ipahal_stream */
IPACM_EVENT_MAX
} ipa_cm_event_id;
@@ -351,4 +353,17 @@ typedef struct _ipacm_ifacemgr_data
uint8_t mac_addr[IPA_MAC_ADDR_SIZE];
}ipacm_ifacemgr_data;
+typedef struct _ipacm_offload_prefix {
+ enum ipa_ip_type iptype;
+ uint32_t v4Addr;
+ uint32_t v4Mask;
+ uint32_t v6Addr[4];
+ uint32_t v6Mask[4];
+} ipacm_offload_prefix;
+
+typedef struct {
+ int if_index;
+ _ipacm_offload_prefix prefix;
+} ipacm_event_ipahal_stream;
+
#endif /* IPA_CM_DEFS_H */
diff --git a/msm8998/ipacm/inc/IPACM_Lan.h b/msm8998/ipacm/inc/IPACM_Lan.h
index 6c54f5e..85ea927 100644
--- a/msm8998/ipacm/inc/IPACM_Lan.h
+++ b/msm8998/ipacm/inc/IPACM_Lan.h
@@ -224,6 +224,10 @@ protected:
uint32_t ipv6_prefix[2];
+ bool is_upstream_set[IPA_IP_MAX];
+ bool is_downstream_set[IPA_IP_MAX];
+ _ipacm_offload_prefix prefix[IPA_IP_MAX];
+
private:
/* get hdr proc ctx type given source and destination l2 hdr type */
diff --git a/msm8998/ipacm/inc/IPACM_OffloadManager.h b/msm8998/ipacm/inc/IPACM_OffloadManager.h
new file mode 100644
index 0000000..85a2063
--- /dev/null
+++ b/msm8998/ipacm/inc/IPACM_OffloadManager.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _IPACM_OFFLOAD_MANAGER_H_
+#define _IPACM_OFFLOAD_MANAGER_H_
+
+
+#include <stdint.h>
+#include <IOffloadManager.h>
+#include "IPACM_Defs.h"
+
+using RET = ::IOffloadManager::RET;
+using Prefix = ::IOffloadManager::Prefix;
+using IP_FAM = ::IOffloadManager::IP_FAM;
+using L4Protocol = ::IOffloadManager::ConntrackTimeoutUpdater::L4Protocol;
+using natTimeoutUpdate_t = ::IOffloadManager::ConntrackTimeoutUpdater::natTimeoutUpdate_t;
+//using ipAddrPortPair_t = ::IOffloadManager::ConntrackTimeoutUpdater::ipAddrPortPair_t;
+//using UDP = ::IOffloadManager::ConntrackTimeoutUpdater::UDP;
+//using TCP = ::IOffloadManager::ConntrackTimeoutUpdater::TCP;
+
+
+
+class IPACM_OffloadManager : public IOffloadManager
+{
+
+public:
+
+ IPACM_OffloadManager();
+ static IPACM_OffloadManager* GetInstance();
+
+ virtual RET registerEventListener(IpaEventListener* /* listener */);
+ virtual RET unregisterEventListener(IpaEventListener* /* listener */);
+ virtual RET registerCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */);
+ virtual RET unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* /* cb */);
+
+ virtual RET provideFd(int /* fd */, unsigned int /* group */);
+ virtual RET clearAllFds();
+ virtual bool isStaApSupported();
+
+ /* ---------------------------- ROUTE ------------------------------- */
+ virtual RET setLocalPrefixes(std::vector<Prefix> &/* prefixes */);
+ virtual RET addDownstream(const char * /* downstream */,
+ const Prefix & /* prefix */);
+ virtual RET removeDownstream(const char * /* downstream */,
+ const Prefix &/* prefix */);
+ virtual RET setUpstream(const char* /* iface */, const Prefix& /* v4Gw */, const Prefix& /* v6Gw */);
+ virtual RET stopAllOffload();
+
+ /* ------------------------- STATS/POLICY --------------------------- */
+ virtual RET setQuota(const char * /* upstream */, uint64_t /* limit */);
+ virtual RET getStats(const char * /* upstream */, bool /* reset */,
+ OffloadStatistics& /* ret */);
+
+ static IPACM_OffloadManager *pInstance; //sky
+
+ IpaEventListener *elrInstance;
+
+ ConntrackTimeoutUpdater *touInstance;
+
+private:
+
+ bool upstream_v4_up;
+
+ bool upstream_v6_up;
+
+ int default_gw_index;
+
+ int post_route_evt(enum ipa_ip_type iptype, int index, ipa_cm_event_id event, const Prefix &gw_addr);
+
+ int ipa_get_if_index(const char *if_name, int *if_index);
+
+ int resetTetherStats(const char *upstream_name);
+
+ static const char *DEVICE_NAME;
+
+}; /* IPACM_OffloadManager */
+
+#endif /* _IPACM_OFFLOAD_MANAGER_H_ */
diff --git a/msm8998/ipacm/inc/IPACM_Wan.h b/msm8998/ipacm/inc/IPACM_Wan.h
index fe6d35e..3ed58fe 100644
--- a/msm8998/ipacm/inc/IPACM_Wan.h
+++ b/msm8998/ipacm/inc/IPACM_Wan.h
@@ -104,6 +104,10 @@ public:
static bool isWanUP(int ipa_if_num_tether)
{
#ifdef FEATURE_IPA_ANDROID
+#ifdef FEATURE_IPACM_HAL
+ return wan_up;
+#else
+
int i;
for (i=0; i < ipa_if_num_tether_v4_total;i++)
{
@@ -116,6 +120,7 @@ public:
}
}
return false;
+#endif
#else
return wan_up;
#endif
diff --git a/msm8998/ipacm/src/Android.mk b/msm8998/ipacm/src/Android.mk
index 4af84c8..26b1ba5 100644
--- a/msm8998/ipacm/src/Android.mk
+++ b/msm8998/ipacm/src/Android.mk
@@ -12,11 +12,13 @@ include $(CLEAR_VARS)
LOCAL_C_INCLUDES := $(LOCAL_PATH)/../src
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../inc
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../ipanat/inc
+LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../hal/inc
ifeq ($(call is-platform-sdk-version-at-least,20),true)
LOCAL_C_INCLUDES += external/icu/icu4c/source/common
else
LOCAL_C_INCLUDES += external/icu4c/common
endif
+#LOCAL_C_INCLUDES += external/dhcpcd
LOCAL_C_INCLUDES += external/libxml2/include
LOCAL_C_INCLUDES += external/libnetfilter_conntrack/include
LOCAL_C_INCLUDES += external/libnfnetlink/include
@@ -26,9 +28,9 @@ LOCAL_C_INCLUDES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
endif
-
LOCAL_CFLAGS := -v
LOCAL_CFLAGS += -DFEATURE_IPA_ANDROID
+LOCAL_CFLAGS += -DFEATURE_IPACM_HAL
ifneq (,$(filter userdebug eng, $(TARGET_BUILD_VARIANT)))
LOCAL_CFLAGS += -DDEBUG
endif
@@ -55,15 +57,32 @@ LOCAL_SRC_FILES := IPACM_Main.cpp \
IPACM_Conntrack_NATApp.cpp\
IPACM_ConntrackClient.cpp \
IPACM_ConntrackListener.cpp \
- IPACM_Log.cpp
+ IPACM_Log.cpp \
+ IPACM_OffloadManager.cpp
LOCAL_MODULE := ipacm
LOCAL_MODULE_TAGS := optional
-LOCAL_SHARED_LIBRARIES := libipanat
+LOCAL_SHARED_LIBRARIES := liboffloadhal
+LOCAL_SHARED_LIBRARIES += libipanat
LOCAL_SHARED_LIBRARIES += libxml2
LOCAL_SHARED_LIBRARIES += libnfnetlink
LOCAL_SHARED_LIBRARIES += libnetfilter_conntrack
+LOCAL_SHARED_LIBRARIES += libhwbinder \
+ libhidlbase \
+ libhidltransport \
+ liblog \
+ libcutils \
+ libdl \
+ libbase \
+ libutils \
+ libhardware_legacy \
+ libhardware \
+ android.hardware.tetheroffload.config@1.0 \
+ android.hardware.tetheroffload.control@1.0
+
+LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_EXECUTABLES)
+
include $(BUILD_EXECUTABLE)
################################################################################
diff --git a/msm8998/ipacm/src/IPACM_ConntrackClient.cpp b/msm8998/ipacm/src/IPACM_ConntrackClient.cpp
index 146cedb..8cc3407 100644
--- a/msm8998/ipacm/src/IPACM_ConntrackClient.cpp
+++ b/msm8998/ipacm/src/IPACM_ConntrackClient.cpp
@@ -60,6 +60,10 @@ IPACM_ConntrackClient::IPACM_ConntrackClient()
udp_hdl = NULL;
tcp_filter = NULL;
udp_filter = NULL;
+ fd_tcp = -1;
+ fd_udp = -1;
+ subscrips_tcp = NF_NETLINK_CONNTRACK_UPDATE | NF_NETLINK_CONNTRACK_DESTROY;
+ subscrips_udp = NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY;
}
IPACM_ConntrackClient* IPACM_ConntrackClient::GetInstance()
@@ -421,10 +425,20 @@ void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *)
subscrips |= NF_NETLINK_CONNTRACK_NEW;
#endif
+#ifdef FEATURE_IPACM_HAL
+ if (pClient->fd_tcp < 0) {
+ IPACMERR("unable to get conntrack TCP handle due to fd_tcp is invalid \n");
+ return NULL;
+ } else {
+ pClient->tcp_hdl = nfct_open2(CONNTRACK, subscrips, pClient->fd_tcp);
+ }
+#else
pClient->tcp_hdl = nfct_open(CONNTRACK, subscrips);
+#endif
+
if(pClient->tcp_hdl == NULL)
{
- PERROR("nfct_open\n");
+ PERROR("nfct_open failed on getting tcp_hdl\n");
return NULL;
}
@@ -475,7 +489,11 @@ void* IPACM_ConntrackClient::TCPRegisterWithConnTrack(void *)
/* de-register the callback */
nfct_callback_unregister(pClient->tcp_hdl);
/* close the handle */
+#ifdef FEATURE_IPACM_HAL
+ nfct_close2(pClient->tcp_hdl, true);
+#else
nfct_close(pClient->tcp_hdl);
+#endif
pClient->tcp_hdl = NULL;
pthread_exit(NULL);
@@ -497,11 +515,21 @@ void* IPACM_ConntrackClient::UDPRegisterWithConnTrack(void *)
return NULL;
}
+#ifdef FEATURE_IPACM_HAL
+ if (pClient->fd_udp < 0) {
+ IPACMERR("unable to get conntrack UDP handle due to fd_udp is invalid \n");
+ return NULL;
+ } else {
+ pClient->udp_hdl = nfct_open2(CONNTRACK,
+ (NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY), pClient->fd_udp);
+ }
+#else
pClient->udp_hdl = nfct_open(CONNTRACK,
(NF_NETLINK_CONNTRACK_NEW | NF_NETLINK_CONNTRACK_DESTROY));
+#endif
if(pClient->udp_hdl == NULL)
{
- PERROR("nfct_open\n");
+ PERROR("nfct_open failed on getting udp_hdl\n");
return NULL;
}
@@ -551,13 +579,51 @@ ctcatch:
/* de-register the callback */
nfct_callback_unregister(pClient->udp_hdl);
/* close the handle */
+#ifdef FEATURE_IPACM_HAL
+ nfct_close2(pClient->udp_hdl, true);
+#else
nfct_close(pClient->udp_hdl);
+#endif
pClient->udp_hdl = NULL;
pthread_exit(NULL);
return NULL;
}
+/* Thread to initialize TCP Conntrack Filters*/
+void IPACM_ConntrackClient::UNRegisterWithConnTrack(void)
+{
+ int ret;
+ IPACM_ConntrackClient *pClient = NULL;
+
+ IPACMDBG("\n");
+
+ /* destroy the TCP filter.. this will not detach the filter */
+ nfct_filter_destroy(pClient->tcp_filter);
+ pClient->tcp_filter = NULL;
+
+ /* de-register the callback */
+ nfct_callback_unregister(pClient->tcp_hdl);
+ /* close the handle */
+ nfct_close(pClient->tcp_hdl);
+ pClient->tcp_hdl = NULL;
+
+ /* destroy the filter.. this will not detach the filter */
+ nfct_filter_destroy(pClient->udp_filter);
+ pClient->udp_filter = NULL;
+
+ /* de-register the callback */
+ nfct_callback_unregister(pClient->udp_hdl);
+ /* close the handle */
+ nfct_close(pClient->udp_hdl);
+ pClient->udp_hdl = NULL;
+
+ pClient->fd_tcp = 0;
+ pClient->fd_udp = 0;
+
+ return;
+}
+
void IPACM_ConntrackClient::UpdateUDPFilters(void *param, bool isWan)
{
static bool isIgnore = false;
diff --git a/msm8998/ipacm/src/IPACM_ConntrackListener.cpp b/msm8998/ipacm/src/IPACM_ConntrackListener.cpp
index ad3fa1e..de0e7e7 100644
--- a/msm8998/ipacm/src/IPACM_ConntrackListener.cpp
+++ b/msm8998/ipacm/src/IPACM_ConntrackListener.cpp
@@ -115,9 +115,12 @@ void IPACM_ConntrackListener::event_callback(ipa_cm_event_id evt,
IPACMDBG_H("Received event: %d with ifname: %s and address: 0x%x\n",
evt, ((ipacm_event_iface_up *)data)->ifname,
((ipacm_event_iface_up *)data)->ipv4_addr);
- CreateConnTrackThreads();
- IPACM_ConntrackClient::UpdateUDPFilters(data, false);
- IPACM_ConntrackClient::UpdateTCPFilters(data, false);
+ if(isWanUp())
+ {
+ CreateConnTrackThreads();
+ IPACM_ConntrackClient::UpdateUDPFilters(data, false);
+ IPACM_ConntrackClient::UpdateTCPFilters(data, false);
+ }
break;
case IPA_NEIGH_CLIENT_IP_ADDR_ADD_EVENT:
diff --git a/msm8998/ipacm/src/IPACM_Conntrack_NATApp.cpp b/msm8998/ipacm/src/IPACM_Conntrack_NATApp.cpp
index f0bdd99..2c06642 100644
--- a/msm8998/ipacm/src/IPACM_Conntrack_NATApp.cpp
+++ b/msm8998/ipacm/src/IPACM_Conntrack_NATApp.cpp
@@ -28,6 +28,9 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "IPACM_Conntrack_NATApp.h"
#include "IPACM_ConntrackClient.h"
+#ifdef FEATURE_IPACM_HAL
+#include "IPACM_OffloadManager.h"
+#endif
#define INVALID_IP_ADDR 0x0
@@ -400,11 +403,16 @@ int NatApp::AddEntry(const nat_table_entry *rule)
void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts)
{
int ret;
+#ifdef FEATURE_IPACM_HAL
+ IOffloadManager::ConntrackTimeoutUpdater::natTimeoutUpdate_t entry;
+ IPACM_OffloadManager* OffloadMng;
+#endif
iptodot("Private IP:", rule->private_ip);
iptodot("Target IP:", rule->target_ip);
IPACMDBG("Private Port: %d, Target Port: %d\n", rule->private_port, rule->target_port);
+#ifndef FEATURE_IPACM_HAL
if(!ct_hdl)
{
ct_hdl = nfct_open(CONNTRACK, 0);
@@ -477,7 +485,47 @@ void NatApp::UpdateCTUdpTs(nat_table_entry *rule, uint32_t new_ts)
rule->timestamp = new_ts;
IPACMDBG("Updated time stamp successfully\n");
}
+#else
+ if(rule->protocol == IPPROTO_UDP)
+ {
+ entry.proto = IOffloadManager::ConntrackTimeoutUpdater::UDP;;
+ }
+ else
+ {
+ entry.proto = IOffloadManager::ConntrackTimeoutUpdater::TCP;
+ }
+ if(rule->dst_nat == false)
+ {
+ entry.src.ipAddr = rule->private_ip;
+ entry.src.port = rule->private_port;
+ entry.dst.ipAddr = rule->target_ip;
+ entry.dst.port = rule->target_port;
+ IPACMDBG("dst nat is not set\n");
+ }
+ else
+ {
+ entry.src.ipAddr = rule->target_ip;
+ entry.src.port = rule->target_port;
+ entry.dst.ipAddr = pub_ip_addr;
+ entry.dst.port = rule->public_port;
+ IPACMDBG("dst nat is set\n");
+ }
+
+ iptodot("Source IP:", entry.src.ipAddr);
+ iptodot("Destination IP:", entry.dst.ipAddr);
+ IPACMDBG("Source Port: %d, Destination Port: %d\n",
+ entry.src.port, entry.dst.port);
+
+ OffloadMng = IPACM_OffloadManager::GetInstance();
+ if (OffloadMng->touInstance == NULL) {
+ IPACMERR("OffloadMng->touInstance is NULL, can't forward to framework!\n");
+ } else {
+ OffloadMng->touInstance->updateTimeout(entry);
+ IPACMDBG("Updated time stamp successfully\n");
+ rule->timestamp = new_ts;
+ }
+#endif
return;
}
diff --git a/msm8998/ipacm/src/IPACM_IfaceManager.cpp b/msm8998/ipacm/src/IPACM_IfaceManager.cpp
index a142553..eab43fd 100644
--- a/msm8998/ipacm/src/IPACM_IfaceManager.cpp
+++ b/msm8998/ipacm/src/IPACM_IfaceManager.cpp
@@ -267,6 +267,10 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param)
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, lan);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, lan);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, lan);
+#ifdef FEATURE_IPACM_HAL
+ IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_ADD, lan);
+ IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_DEL, lan);
+#endif
#else
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, lan);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, lan);
@@ -374,6 +378,10 @@ int IPACM_IfaceManager::create_iface_instance(ipacm_ifacemgr_data *param)
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6_TETHER, wl);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_TETHER, wl);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_DOWN_V6_TETHER, wl);
+#ifdef FEATURE_IPACM_HAL
+ IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_ADD, wl);
+ IPACM_EvtDispatcher::registr(IPA_DOWNSTREAM_DEL, wl);
+#endif
#else
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP, wl);
IPACM_EvtDispatcher::registr(IPA_HANDLE_WAN_UP_V6, wl);
diff --git a/msm8998/ipacm/src/IPACM_Lan.cpp b/msm8998/ipacm/src/IPACM_Lan.cpp
index 991e451..8d853d2 100644
--- a/msm8998/ipacm/src/IPACM_Lan.cpp
+++ b/msm8998/ipacm/src/IPACM_Lan.cpp
@@ -171,9 +171,17 @@ IPACM_Lan::IPACM_Lan(int iface_index) : IPACM_Iface(iface_index)
/* set the IPA-client pipe enum */
if(ipa_if_cate == LAN_IF)
{
+#ifdef FEATURE_IPACM_HAL
+ handle_tethering_client(false, IPACM_CLIENT_MAX);
+#else
handle_tethering_client(false, IPACM_CLIENT_USB);
+#endif
}
#endif
+
+ memset(is_downstream_set, 0, sizeof(is_downstream_set));
+ memset(is_upstream_set, 0, sizeof(is_upstream_set));
+ memset(&prefix, 0, sizeof(prefix));
return;
}
@@ -375,6 +383,9 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
handle_wan_up(IPA_IP_v4);
}
}
+ IPACMDBG_H("Finished checking wan_up\n");
+ } else {
+ IPACMDBG_H("Wan_V4 haven't up yet\n");
}
if(IPACM_Wan::isWanUP_V6(ipa_if_num))
@@ -393,6 +404,9 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
handle_wan_up(IPA_IP_v6);
}
}
+ IPACMDBG_H("Finished checking wan_up_v6\n");
+ } else {
+ IPACMDBG_H("Wan_V6 haven't up yet\n");
}
/* Post event to NAT */
@@ -451,20 +465,41 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
+ {
+ IPACMERR("IPA_HANDLE_WAN_UP_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
+ return;
+ }
+#endif
+ if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
{
- if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+#ifdef FEATURE_IPACM_HAL
+ if (is_upstream_set[IPA_IP_v4] == false)
{
- if(data_wan_tether->is_sta == false)
+ IPACMDBG_H("Add upstream for IPv4.\n");
+ is_upstream_set[IPA_IP_v4] = true;
+ 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)
+ {
+ ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
+ handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
+ } else {
+ handle_wan_up(IPA_IP_v4);
+ }
+ }
+ }
+#else
+ if (data_wan_tether->is_sta == false)
+ {
ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
- }
- else
- {
+ } else {
handle_wan_up(IPA_IP_v4);
- }
}
+#endif
}
break;
@@ -472,7 +507,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6_TETHER event\n");
data_wan_tether = (ipacm_event_iface_up_tehter*)param;
- if(data_wan_tether == NULL)
+ if (data_wan_tether == NULL)
{
IPACMERR("No event data is found.\n");
return;
@@ -480,13 +515,27 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
+ {
+ 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
+ if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
{
- if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+#ifdef FEATURE_IPACM_HAL
+ if (is_upstream_set[IPA_IP_v6] == false)
{
+ IPACMDBG_H("Add upstream for IPv6.\n");
+ is_upstream_set[IPA_IP_v6] = true;
+
+ if (is_downstream_set[IPA_IP_v6] == true)
+ {
+ 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->is_sta == false)
{
ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
@@ -495,14 +544,24 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
{
handle_wan_up(IPA_IP_v6);
}
+ }
}
+#else
+ if (data_wan_tether->is_sta == false)
+ {
+ 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
}
break;
case IPA_HANDLE_WAN_DOWN_TETHER:
IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_TETHER event\n");
data_wan_tether = (ipacm_event_iface_up_tehter*)param;
- if(data_wan_tether == NULL)
+ if (data_wan_tether == NULL)
{
IPACMERR("No event data is found.\n");
return;
@@ -510,12 +569,29 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
+ {
+ 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
+ if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
{
- if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+#ifdef FEATURE_IPACM_HAL
+ if(is_upstream_set[IPA_IP_v4] == true)
{
- handle_wan_down(data_wan_tether->is_sta);
+ IPACMDBG_H("Del upstream for IPv4.\n");
+ is_upstream_set[IPA_IP_v4] = false;
+ 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);
+ }
}
+#else
+ handle_wan_down(data_wan_tether->is_sta);
+#endif
}
break;
@@ -530,33 +606,116 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
{
- /* clean up v6 RT rules*/
- IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6_TETHER in LAN-instance and need clean up client IPv6 address \n");
+ 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
+ if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ {
+#ifdef FEATURE_IPACM_HAL
+ if (is_upstream_set[IPA_IP_v6] == true)
+ {
+ IPACMDBG_H("Del upstream for IPv6.\n");
+ is_upstream_set[IPA_IP_v6] = false;
+ if(is_downstream_set[IPA_IP_v6] == true)
+ {
+ 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);
+ }
+ }
+#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
+ }
+ break;
- if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ case IPA_DOWNSTREAM_ADD:
+ {
+ ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param;
+ ipa_interface_index = iface_ipa_index_query(data->if_index);
+ if (ipa_interface_index == ipa_if_num)
+ {
+ IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n");
+ if (is_downstream_set[data->prefix.iptype] == false)
{
- handle_wan_down_v6(data_wan_tether->is_sta);
+ IPACMDBG_H("Add downstream for IP iptype %d\n", data->prefix.iptype);
+ is_downstream_set[data->prefix.iptype] = true;
+ memcpy(&prefix[data->prefix.iptype], &data->prefix,
+ sizeof(prefix[data->prefix.iptype]));
+
+ if (is_upstream_set[data->prefix.iptype] == true)
+ {
+ IPACMDBG_H("Upstream was set before, adding UL rules.\n");
+ if (ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype)
+ {
+ if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */
+ install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+
+ if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */
+ {
+ ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype);
+ handle_wan_up_ex(ext_prop, data->prefix.iptype, 0);
+ } else {
+ handle_wan_up(data->prefix.iptype); /* STA */
+ }
+ }
+ }
+ } else {
+ IPACMDBG_H("downstream for IP iptype %d already set \n", data->prefix.iptype);
}
}
break;
+ }
+
+ case IPA_DOWNSTREAM_DEL:
+ {
+ ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param;
+ ipa_interface_index = iface_ipa_index_query(data->if_index);
+ if (ipa_interface_index == ipa_if_num)
+ {
+ IPACMDBG_H("Received IPA_DOWNSTREAM_DEL event.\n");
+ if (is_downstream_set[data->prefix.iptype] == true)
+ {
+ IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype);
+ is_downstream_set[data->prefix.iptype] = false;
+
+ if (is_upstream_set[data->prefix.iptype] == true)
+ {
+ 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 */
+ } else {
+ handle_lan_client_reset_rt(IPA_IP_v6);
+ handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */
+ }
+ }
+ }
+ }
+ break;
+ }
+
#else
case IPA_HANDLE_WAN_UP:
IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
data_wan = (ipacm_event_iface_up*)param;
- if(data_wan == NULL)
+ if (data_wan == NULL)
{
IPACMERR("No event data is found.\n");
return;
}
IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
- if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
{
- if(data_wan->is_sta == false)
+ if (data_wan->is_sta == false)
{
ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
handle_wan_up_ex(ext_prop, IPA_IP_v4, data_wan->xlat_mux_id);
@@ -572,17 +731,17 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Received IPA_HANDLE_WAN_UP_V6 event\n");
data_wan = (ipacm_event_iface_up*)param;
- if(data_wan == NULL)
+ if (data_wan == NULL)
{
IPACMERR("No event data is found.\n");
return;
}
IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
- if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ 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->is_sta == false)
{
ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
@@ -597,13 +756,13 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
case IPA_HANDLE_WAN_DOWN:
IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN event\n");
data_wan = (ipacm_event_iface_up*)param;
- if(data_wan == NULL)
+ if (data_wan == NULL)
{
IPACMERR("No event data is found.\n");
return;
}
IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
- if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ if (ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
{
handle_wan_down(data_wan->is_sta);
}
@@ -612,7 +771,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
case IPA_HANDLE_WAN_DOWN_V6:
IPACMDBG_H("Received IPA_HANDLE_WAN_DOWN_V6 event\n");
data_wan = (ipacm_event_iface_up*)param;
- if(data_wan == NULL)
+ if (data_wan == NULL)
{
IPACMERR("No event data is found.\n");
return;
@@ -623,7 +782,7 @@ void IPACM_Lan::event_callback(ipa_cm_event_id event, void *param)
handle_lan_client_reset_rt(IPA_IP_v6);
IPACMDBG_H("Backhaul is sta mode?%d\n", data_wan->is_sta);
- if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ if (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
{
handle_wan_down_v6(data_wan->is_sta);
}
@@ -1267,6 +1426,12 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type)
flt_rule_entry.rule.attrib.u.v4.dst_addr_mask = 0x0;
flt_rule_entry.rule.attrib.u.v4.dst_addr = 0x0;
+/* 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.v4.dst_addr_mask = prefix[IPA_IP_v4].v4Mask;
+ flt_rule_entry.rule.attrib.u.v4.dst_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))
{
@@ -1338,6 +1503,19 @@ int IPACM_Lan::handle_wan_up(ipa_ip_type ip_type)
flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = 0x00000000;
flt_rule_entry.rule.attrib.u.v6.dst_addr[3] = 0X00000000;
+/* 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.dst_addr_mask[0] = prefix[IPA_IP_v6].v6Mask[0];
+ flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[1] = prefix[IPA_IP_v6].v6Mask[1];
+ flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[2] = prefix[IPA_IP_v6].v6Mask[2];
+ flt_rule_entry.rule.attrib.u.v6.dst_addr_mask[3] = prefix[IPA_IP_v6].v6Mask[3];
+ flt_rule_entry.rule.attrib.u.v6.dst_addr[0] = prefix[IPA_IP_v6].v6Addr[0];
+ flt_rule_entry.rule.attrib.u.v6.dst_addr[1] = prefix[IPA_IP_v6].v6Addr[1];
+ flt_rule_entry.rule.attrib.u.v6.dst_addr[2] = prefix[IPA_IP_v6].v6Addr[2];
+ flt_rule_entry.rule.attrib.u.v6.dst_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))
{
@@ -1796,8 +1974,6 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp
uint32_t tx_index;
int eth_index,v6_num;
const int NUM = 1;
- char cmd[200] = {0};
- uint32_t ipv4_addr;
if(tx_prop == NULL)
{
@@ -1875,17 +2051,6 @@ int IPACM_Lan::handle_eth_client_route_rule(uint8_t *mac_addr, ipa_ip_type iptyp
IPACMDBG_H("client(%d): v4 header handle:(0x%x)\n",
eth_index,
get_client_memptr(eth_client, eth_index)->hdr_hdl_v4);
-
- /* add static arp entry */
- ipv4_addr = get_client_memptr(eth_client, eth_index)->v4_addr;
- snprintf(cmd, sizeof(cmd), "ip neighbor change %d.%d.%d.%d lladdr %02x:%02x:%02x:%02x:%02x:%02x dev %s nud permanent",
- (unsigned char)(ipv4_addr >> 24), (unsigned char)(ipv4_addr >> 16),
- (unsigned char)(ipv4_addr >> 8), (unsigned char)ipv4_addr,
- mac_addr[0], mac_addr[1], mac_addr[2], mac_addr[3], mac_addr[4], mac_addr[5],
- dev_name);
- IPACMDBG_H("%s\n", cmd);
- system(cmd);
-
strlcpy(rt_rule->rt_tbl_name,
IPACM_Iface::ipacmcfg->rt_tbl_lan_v4.name,
sizeof(rt_rule->rt_tbl_name));
@@ -2340,8 +2505,6 @@ int IPACM_Lan::handle_eth_client_down_evt(uint8_t *mac_addr)
uint32_t tx_index;
int num_eth_client_tmp = num_eth_client;
int num_v6;
- char cmd[200] = {0};
- uint32_t ipv4_addr;
IPACMDBG_H("total client: %d\n", num_eth_client_tmp);
@@ -2400,13 +2563,6 @@ int IPACM_Lan::handle_eth_client_down_evt(uint8_t *mac_addr)
get_client_memptr(eth_client, clt_indx)->route_rule_set_v4 = false;
get_client_memptr(eth_client, clt_indx)->route_rule_set_v6 = 0;
- ipv4_addr = get_client_memptr(eth_client, clt_indx)->v4_addr;
- snprintf(cmd, sizeof(cmd), "ip neighbor del %d.%d.%d.%d dev %s",
- (unsigned char)(ipv4_addr >> 24), (unsigned char)(ipv4_addr >> 16),
- (unsigned char)(ipv4_addr >> 8), (unsigned char)ipv4_addr, dev_name);
- system(cmd);
- IPACMDBG_H("%s\n", cmd);
-
for (; clt_indx < num_eth_client_tmp - 1; clt_indx++)
{
memcpy(get_client_memptr(eth_client, clt_indx)->mac,
@@ -2472,8 +2628,6 @@ int IPACM_Lan::handle_down_evt()
{
int i;
int res = IPACM_SUCCESS;
- char cmd[200] = {0};
- uint32_t ipv4_addr;
IPACMDBG_H("lan handle_down_evt\n ");
if (ipa_if_cate == ODU_IF)
@@ -2656,7 +2810,11 @@ int IPACM_Lan::handle_down_evt()
/* reset the IPA-client pipe enum */
if(ipa_if_cate != WAN_IF)
{
+#ifdef FEATURE_IPACM_HAL
+ handle_tethering_client(true, IPACM_CLIENT_MAX);
+#else
handle_tethering_client(true, IPACM_CLIENT_USB);
+#endif
}
#endif /* defined(FEATURE_IPA_ANDROID)*/
fail:
@@ -2664,13 +2822,6 @@ fail:
IPACMDBG_H("left %d eth clients need to be deleted \n ", num_eth_client);
for (i = 0; i < num_eth_client; i++)
{
- ipv4_addr = get_client_memptr(eth_client, i)->v4_addr;
- snprintf(cmd, sizeof(cmd), "ip neighbor del %d.%d.%d.%d dev %s",
- (unsigned char)(ipv4_addr >> 24), (unsigned char)(ipv4_addr >> 16),
- (unsigned char)(ipv4_addr >> 8), (unsigned char)ipv4_addr, dev_name);
- system(cmd);
- IPACMDBG_H("%s\n", cmd);
-
/* First reset nat rules and then route rules */
if(get_client_memptr(eth_client, i)->ipv4_set == true)
{
@@ -2763,7 +2914,7 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptyp
ipa_ioc_add_flt_rule *pFilteringTable;
ipa_fltr_installed_notif_req_msg_v01 flt_index;
int fd;
- int i, index;
+ int i, index, eq_index;
uint32_t value = 0;
IPACMDBG_H("Set modem UL flt rules\n");
@@ -2885,6 +3036,73 @@ int IPACM_Lan::handle_uplink_filter_rule(ipacm_ext_prop *prop, ipa_ip_type iptyp
IPACMDBG_H("xlat meta-data is modified for rule: %d has index %d with xlat_mux_id: %d\n",
cnt, index, xlat_mux_id);
}
+
+#ifdef FEATURE_IPACM_HAL
+ /* add prefix equation in modem UL rules */
+ if(iptype == IPA_IP_v4)
+ {
+ flt_rule_entry.rule.eq_attrib.num_offset_meq_32++;
+ if(flt_rule_entry.rule.eq_attrib.num_offset_meq_32 <= IPA_IPFLTR_NUM_MEQ_32_EQNS)
+ {
+ eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_32 - 1;
+ if(eq_index == 0)
+ {
+ flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<5);
+ }
+ else
+ {
+ flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<6);
+ }
+ flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].offset = 12;
+ flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].mask = prefix[IPA_IP_v4].v4Mask;
+ flt_rule_entry.rule.eq_attrib.offset_meq_32[eq_index].value = prefix[IPA_IP_v4].v4Addr;
+ }
+ else
+ {
+ IPACMERR("Run out of MEQ32 equation.\n");
+ flt_rule_entry.rule.eq_attrib.num_offset_meq_32--;
+ }
+ }
+ else
+ {
+ flt_rule_entry.rule.eq_attrib.num_offset_meq_128++;
+ if(flt_rule_entry.rule.eq_attrib.num_offset_meq_128 <= IPA_IPFLTR_NUM_MEQ_128_EQNS)
+ {
+ eq_index = flt_rule_entry.rule.eq_attrib.num_offset_meq_128 - 1;
+ if(eq_index == 0)
+ {
+ flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<3);
+ }
+ else
+ {
+ flt_rule_entry.rule.eq_attrib.rule_eq_bitmap |= (1<<4);
+ }
+ flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].offset = 8;
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 0)
+ = prefix[IPA_IP_v6].v6Mask[0];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 4)
+ = prefix[IPA_IP_v6].v6Mask[1];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 8)
+ = prefix[IPA_IP_v6].v6Mask[2];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].mask + 12)
+ = prefix[IPA_IP_v6].v6Mask[3];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 0)
+ = prefix[IPA_IP_v6].v6Addr[0];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 4)
+ = prefix[IPA_IP_v6].v6Addr[1];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 8)
+ = prefix[IPA_IP_v6].v6Addr[2];
+ *(uint32_t *)(flt_rule_entry.rule.eq_attrib.offset_meq_128[eq_index].value + 12)
+ = prefix[IPA_IP_v6].v6Addr[3];
+ }
+ else
+ {
+ IPACMERR("Run out of MEQ128 equation.\n");
+ flt_rule_entry.rule.eq_attrib.num_offset_meq_128--;
+ }
+ }
+#endif
+
#ifdef FEATURE_IPA_V3
flt_rule_entry.rule.hashable = prop->prop[cnt].is_rule_hashable;
flt_rule_entry.rule.rule_id = prop->prop[cnt].rule_id;
diff --git a/msm8998/ipacm/src/IPACM_Main.cpp b/msm8998/ipacm/src/IPACM_Main.cpp
index c6ab9ee..347bb88 100644
--- a/msm8998/ipacm/src/IPACM_Main.cpp
+++ b/msm8998/ipacm/src/IPACM_Main.cpp
@@ -68,6 +68,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "IPACM_ConntrackClient.h"
#include "IPACM_Netlink.h"
+#ifdef FEATURE_IPACM_HAL
+#include "IPACM_OffloadManager.h"
+#include <HAL.h>
+#endif
+
/* not defined(FEATURE_IPA_ANDROID)*/
#ifndef FEATURE_IPA_ANDROID
#include "IPACM_LanToLan.h"
@@ -78,7 +83,7 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define IPACM_FIREWALL_FILE_NAME "mobileap_firewall.xml"
#define IPACM_CFG_FILE_NAME "IPACM_cfg.xml"
#ifdef FEATURE_IPA_ANDROID
-#define IPACM_PID_FILE "/data/misc/ipa/ipacm.pid"
+#define IPACM_PID_FILE "/data/vendor/misc/ipa/ipacm.pid"
#define IPACM_DIR_NAME "/data"
#else/* defined(FEATURE_IPA_ANDROID) */
#define IPACM_PID_FILE "/etc/ipacm.pid"
@@ -218,6 +223,7 @@ void* ipa_driver_msg_notifier(void *param)
struct ipa_wlan_msg_ex *event_ex= NULL;
struct ipa_get_data_stats_resp_msg_v01 event_data_stats;
struct ipa_get_apn_data_stats_resp_msg_v01 event_network_stats;
+ IPACM_OffloadManager* OffloadMng;
ipacm_cmd_q_data evt_data;
ipacm_event_data_mac *data = NULL;
@@ -671,7 +677,35 @@ void* ipa_driver_msg_notifier(void *param)
evt_data.event = IPA_NETWORK_STATS_UPDATE_EVENT;
evt_data.evt_data = data_network_stats;
break;
-
+#ifdef FEATURE_IPACM_HAL
+ case IPA_QUOTA_REACH:
+ IPACMDBG_H("Received IPA_QUOTA_REACH\n");
+ OffloadMng = IPACM_OffloadManager::GetInstance();
+ if (OffloadMng->elrInstance == NULL) {
+ IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n");
+ } else {
+ OffloadMng->elrInstance->onLimitReached();
+ }
+ break;
+ case IPA_SSR_BEFORE_SHUTDOWN:
+ IPACMDBG_H("Received IPA_SSR_BEFORE_SHUTDOWN\n");
+ OffloadMng = IPACM_OffloadManager::GetInstance();
+ if (OffloadMng->elrInstance == NULL) {
+ IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n");
+ } else {
+ OffloadMng->elrInstance->onOffloadStopped(IpaEventRelay::ERROR);
+ }
+ break;
+ case IPA_SSR_AFTER_POWERUP:
+ IPACMDBG_H("Received IPA_SSR_AFTER_POWERUP\n");
+ OffloadMng = IPACM_OffloadManager::GetInstance();
+ if (OffloadMng->elrInstance == NULL) {
+ IPACMERR("OffloadMng->elrInstance is NULL, can't forward to framework!\n");
+ } else {
+ OffloadMng->elrInstance->onOffloadSupportAvailable();
+ }
+ break;
+#endif
default:
IPACMDBG_H("Unhandled message type: %d\n", event_hdr.msg_type);
continue;
@@ -733,6 +767,7 @@ int main(int argc, char **argv)
int ret;
pthread_t netlink_thread = 0, monitor_thread = 0, ipa_driver_thread = 0;
pthread_t cmd_queue_thread = 0;
+ IPACM_OffloadManager* OffloadMng;
/* check if ipacm is already running or not */
ipa_is_ipacm_running();
@@ -740,12 +775,16 @@ int main(int argc, char **argv)
IPACMDBG_H("In main()\n");
IPACM_Neighbor *neigh = new IPACM_Neighbor();
IPACM_IfaceManager *ifacemgr = new IPACM_IfaceManager();
+#ifdef FEATURE_IPACM_HAL
+ OffloadMng = IPACM_OffloadManager::GetInstance();
+ HAL *hal = HAL::makeIPAHAL(1, OffloadMng);
+ IPACMDBG_H(" START IPACM_OffloadManager and link to android framework\n");
+#endif
#ifdef FEATURE_ETH_BRIDGE_LE
IPACM_LanToLan* lan2lan = new IPACM_LanToLan();
#endif
- IPACM_ConntrackClient *cc = IPACM_ConntrackClient::GetInstance();
CtList = new IPACM_ConntrackListener();
IPACMDBG_H("Staring IPA main\n");
diff --git a/msm8998/ipacm/src/IPACM_OffloadManager.cpp b/msm8998/ipacm/src/IPACM_OffloadManager.cpp
new file mode 100644
index 0000000..332abd5
--- /dev/null
+++ b/msm8998/ipacm/src/IPACM_OffloadManager.cpp
@@ -0,0 +1,540 @@
+/*
+Copyright (c) 2017, The Linux Foundation. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+* Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above
+ copyright notice, this list of conditions and the following
+ disclaimer in the documentation and/or other materials provided
+ with the distribution.
+* Neither the name of The Linux Foundation nor the names of its
+ contributors may be used to endorse or promote products derived
+ from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.Z
+*/
+/*!
+ @file
+ IPACM_OffloadManager.cpp
+
+ @brief
+ This file implements the basis Iface functionality.
+
+ @Author
+ Skylar Chang
+
+*/
+#include <IPACM_OffloadManager.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <string.h>
+#include "IPACM_ConntrackClient.h"
+#include "IPACM_ConntrackListener.h"
+#include "IPACM_Iface.h"
+#include "IPACM_Config.h"
+
+const char *IPACM_OffloadManager::DEVICE_NAME = "/dev/wwan_ioctl";
+
+/* NatApp class Implementation */
+IPACM_OffloadManager *IPACM_OffloadManager::pInstance = NULL;
+
+IPACM_OffloadManager::IPACM_OffloadManager()
+{
+ default_gw_index = INVALID_IFACE;
+ upstream_v4_up = false;
+ upstream_v6_up = false;
+ return ;
+}
+
+RET IPACM_OffloadManager::registerEventListener(IpaEventListener* eventlistener)
+{
+ RET result = SUCCESS;
+ if (elrInstance == NULL)
+ elrInstance = eventlistener;
+ else {
+ IPACMDBG_H("already register EventListener previously \n");
+ result = FAIL_INPUT_CHECK;
+ }
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::unregisterEventListener(IpaEventListener* )
+{
+ RET result = SUCCESS;
+ if (elrInstance)
+ elrInstance = NULL;
+ else {
+ IPACMDBG_H("already unregisterEventListener previously \n");
+ result = SUCCESS_DUPLICATE_CONFIG;
+ }
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::registerCtTimeoutUpdater(ConntrackTimeoutUpdater* timeoutupdater)
+{
+ RET result = SUCCESS;
+ if (touInstance == NULL)
+ touInstance = timeoutupdater;
+ else {
+ IPACMDBG_H("already register ConntrackTimeoutUpdater previously \n");
+ result = FAIL_INPUT_CHECK;
+ }
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::unregisterCtTimeoutUpdater(ConntrackTimeoutUpdater* )
+{
+ RET result = SUCCESS;
+ if (touInstance)
+ touInstance = NULL;
+ else {
+ IPACMDBG_H("already unregisterCtTimeoutUpdater previously \n");
+ result = SUCCESS_DUPLICATE_CONFIG;
+ }
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::provideFd(int fd, unsigned int groups)
+{
+ IPACM_ConntrackClient *cc;
+ int on = 1, rel;
+
+ cc = IPACM_ConntrackClient::GetInstance();
+
+ if(!cc)
+ {
+ IPACMERR("Init failed: cc %p\n", cc);
+ return FAIL_HARDWARE;
+ }
+
+ if (groups == cc->subscrips_tcp) {
+ cc->fd_tcp = 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) );
+ if (rel == -1)
+ {
+ IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) );
+ }
+ } else if (groups == cc->subscrips_udp) {
+ cc->fd_udp = 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) );
+ if (rel == -1)
+ {
+ IPACMERR( "setsockopt returned error code %d ( %s )", errno, strerror( errno ) );
+ }
+ } else {
+ IPACMERR("Received unexpected fd with groups %d.\n", groups);
+ }
+ if(cc->fd_tcp >0 && cc->fd_udp >0) {
+ IPACMDBG_H(" Got both fds from framework, start conntrack listener thread.\n");
+ CtList->CreateConnTrackThreads();
+ }
+ return SUCCESS;
+}
+
+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();
+
+ return SUCCESS;
+}
+
+bool IPACM_OffloadManager::isStaApSupported()
+{
+ return true;
+}
+
+
+RET IPACM_OffloadManager::setLocalPrefixes(std::vector<Prefix> &/* prefixes */)
+{
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::addDownstream(const char * downstream_name, const Prefix &prefix)
+{
+ int index;
+ ipacm_cmd_q_data evt;
+ 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 {
+ IPACMDBG_H("subnet info v6Addr: %08x:%08x:%08x:%08x \n",
+ prefix.v6Addr[0], prefix.v6Addr[1], prefix.v6Addr[2], prefix.v6Addr[3]);
+ IPACMDBG_H("subnet info v6Mask: %08x:%08x:%08x:%08x \n",
+ prefix.v6Mask[0], prefix.v6Mask[1], prefix.v6Mask[2], prefix.v6Mask[3]);
+ }
+
+ if(ipa_get_if_index(downstream_name, &index))
+ {
+ IPACMERR("fail to get iface index.\n");
+ return FAIL_HARDWARE;
+ }
+
+ evt_data = (ipacm_event_ipahal_stream*)malloc(sizeof(ipacm_event_ipahal_stream));
+ if(evt_data == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return FAIL_HARDWARE;
+ }
+ memset(evt_data, 0, sizeof(*evt_data));
+
+ evt_data->if_index = index;
+ memcpy(&evt_data->prefix, &prefix, sizeof(evt_data->prefix));
+
+ memset(&evt, 0, sizeof(ipacm_cmd_q_data));
+ evt.evt_data = (void*)evt_data;
+ evt.event = IPA_DOWNSTREAM_ADD;
+
+ IPACMDBG_H("Posting event IPA_DOWNSTREAM_ADD\n");
+ IPACM_EvtDispatcher::PostEvt(&evt);
+
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::removeDownstream(const char * downstream_name, const Prefix &prefix)
+{
+ int index;
+ ipacm_cmd_q_data evt;
+ 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))
+ {
+ IPACMERR("fail to get iface index.\n");
+ return FAIL_HARDWARE;
+ }
+
+ evt_data = (ipacm_event_ipahal_stream*)malloc(sizeof(ipacm_event_ipahal_stream));
+ if(evt_data == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return FAIL_HARDWARE;
+ }
+ memset(evt_data, 0, sizeof(*evt_data));
+
+ evt_data->if_index = index;
+ memcpy(&evt_data->prefix, &prefix, sizeof(evt_data->prefix));
+
+ memset(&evt, 0, sizeof(ipacm_cmd_q_data));
+ evt.evt_data = (void*)evt_data;
+ evt.event = IPA_DOWNSTREAM_DEL;
+
+ IPACMDBG_H("Posting event IPA_DOWNSTREAM_DEL\n");
+ IPACM_EvtDispatcher::PostEvt(&evt);
+
+ return SUCCESS;
+}
+
+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 */
+ IPACMDBG_H("setUpstream upstream_name(%s), ipv4-fam(%d) ipv6-fam(%d)\n", upstream_name, gw_addr_v4.fam, gw_addr_v6.fam);
+
+ if(upstream_name == NULL)
+ {
+ if (default_gw_index == INVALID_IFACE) {
+ 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);
+ upstream_v4_up = false;
+ }
+ if (gw_addr_v6.fam == V6 && upstream_v6_up == true) {
+ IPACMDBG_H("clean upstream(%s) for ipv6-fam(%d) upstream_v6_up(%d)\n", upstream_name, gw_addr_v6.fam, upstream_v6_up);
+ post_route_evt(IPA_IP_v6, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v6);
+ upstream_v6_up = false;
+ }
+ default_gw_index = INVALID_IFACE;
+ }
+ else
+ {
+ if(ipa_get_if_index(upstream_name, &index))
+ {
+ IPACMERR("fail to get iface index.\n");
+ return FAIL_INPUT_CHECK;
+ }
+
+ /* reset the stats when switch from LTE->STA */
+ if (index != default_gw_index) {
+ IPACMDBG_H(" interface switched to %s\n", upstream_name);
+ if(memcmp(upstream_name, "wlan0", sizeof("wlan0")) == 0)
+ {
+ IPACMDBG_H("switch to STA mode, need reset wlan-fw stats\n");
+ resetTetherStats(upstream_name);
+ }
+ }
+
+ if (gw_addr_v4.fam == V4 && gw_addr_v6.fam == V6) {
+
+ if (upstream_v4_up == false) {
+ IPACMDBG_H("IPV4 gateway: 0x%x \n", gw_addr_v4.v4Addr);
+ /* posting route add event for both IPv4 and IPv6 */
+ post_route_evt(IPA_IP_v4, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v4);
+ upstream_v4_up = true;
+ } else {
+ IPACMDBG_H("already setupstream iface(%s) ipv4 previously\n", upstream_name);
+ }
+
+ if (upstream_v6_up == false) {
+ IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n",
+ gw_addr_v6.v6Addr[0], gw_addr_v6.v6Addr[1], gw_addr_v6.v6Addr[2], gw_addr_v6.v6Addr[3]);
+ post_route_evt(IPA_IP_v6, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v6);
+ upstream_v6_up = true;
+ } else {
+ IPACMDBG_H("already setupstream iface(%s) ipv6 previously\n", upstream_name);
+ }
+ } else if (gw_addr_v4.fam == V4 ) {
+ IPACMDBG_H("check upstream_v6_up (%d) v4_up (%d), default gw index (%d)\n", upstream_v6_up, upstream_v4_up, default_gw_index);
+ if (upstream_v6_up == true && default_gw_index != INVALID_IFACE ) {
+ /* clean up previous V6 upstream event */
+ IPACMDBG_H(" Post clean-up v6 default gw on iface %d\n", default_gw_index);
+ post_route_evt(IPA_IP_v6, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v6);
+ upstream_v6_up = false;
+ }
+
+ if (upstream_v4_up == false) {
+ IPACMDBG_H("IPV4 gateway: %x \n", gw_addr_v4.v4Addr);
+ /* posting route add event for both IPv4 and IPv6 */
+ post_route_evt(IPA_IP_v4, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v4);
+ upstream_v4_up = true;
+ } else {
+ IPACMDBG_H("already setupstream iface(%s) ipv4 previously\n", upstream_name);
+ result = SUCCESS_DUPLICATE_CONFIG;
+ }
+ } else if (gw_addr_v6.fam == V6) {
+ IPACMDBG_H("check upstream_v6_up (%d) v4_up (%d), default gw index (%d)\n", upstream_v6_up, upstream_v4_up, default_gw_index);
+ if (upstream_v4_up == true && default_gw_index != INVALID_IFACE ) {
+ /* clean up previous V4 upstream event */
+ IPACMDBG_H(" Post clean-up v4 default gw on iface %d\n", default_gw_index);
+ post_route_evt(IPA_IP_v4, default_gw_index, IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT, gw_addr_v4);
+ upstream_v4_up = false;
+ }
+
+ if (upstream_v6_up == false) {
+ IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n",
+ gw_addr_v6.v6Addr[0], gw_addr_v6.v6Addr[1], gw_addr_v6.v6Addr[2], gw_addr_v6.v6Addr[3]);
+ post_route_evt(IPA_IP_v6, index, IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT, gw_addr_v6);
+ upstream_v6_up = true;
+ } else {
+ IPACMDBG_H("already setupstream iface(%s) ipv6 previously\n", upstream_name);
+ result = SUCCESS_DUPLICATE_CONFIG;
+ }
+ }
+ default_gw_index = index;
+ IPACMDBG_H("Change degault_gw netdev to (%s)\n", upstream_name);
+ }
+ return result;
+}
+
+RET IPACM_OffloadManager::stopAllOffload()
+{
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::setQuota(const char * upstream_name /* upstream */, uint64_t mb/* limit */)
+{
+ wan_ioctl_set_data_quota quota;
+ int fd = -1;
+
+ if ((fd = open(DEVICE_NAME, O_RDWR)) < 0)
+ {
+ IPACMERR("Failed opening %s.\n", DEVICE_NAME);
+ return FAIL_HARDWARE;
+ }
+
+ quota.quota_mbytes = mb;
+ quota.set_quota = true;
+
+ memset(quota.interface_name, 0, IFNAMSIZ);
+ if (strlcpy(quota.interface_name, upstream_name, IFNAMSIZ) >= IFNAMSIZ) {
+ IPACMERR("String truncation occurred on upstream");
+ close(fd);
+ return FAIL_INPUT_CHECK;
+ }
+
+ IPACMDBG_H("SET_DATA_QUOTA %s %lld", quota.interface_name, mb);
+
+ if (ioctl(fd, WAN_IOC_SET_DATA_QUOTA, &quota) < 0) {
+ IPACMERR("IOCTL WAN_IOCTL_SET_DATA_QUOTA call failed: %s", strerror(errno));
+ close(fd);
+ return FAIL_TRY_AGAIN;
+ }
+
+ close(fd);
+ return SUCCESS;
+}
+
+RET IPACM_OffloadManager::getStats(const char * upstream_name /* upstream */,
+ bool reset /* reset */, OffloadStatistics& offload_stats/* ret */)
+{
+ int fd = -1;
+ wan_ioctl_query_tether_stats_all stats;
+
+ if ((fd = open(DEVICE_NAME, O_RDWR)) < 0) {
+ IPACMERR("Failed opening %s.\n", DEVICE_NAME);
+ return FAIL_HARDWARE;
+ }
+
+ memset(&stats, 0, sizeof(stats));
+ if (strlcpy(stats.upstreamIface, upstream_name, IFNAMSIZ) >= IFNAMSIZ) {
+ IPACMERR("String truncation occurred on upstream\n");
+ close(fd);
+ return FAIL_INPUT_CHECK;
+ }
+ stats.reset_stats = reset;
+ stats.ipa_client = IPACM_CLIENT_MAX;
+
+ if (ioctl(fd, WAN_IOC_QUERY_TETHER_STATS_ALL, &stats) < 0) {
+ IPACMERR("IOCTL WAN_IOC_QUERY_TETHER_STATS_ALL call failed: %s \n", strerror(errno));
+ close(fd);
+ return FAIL_TRY_AGAIN;
+ }
+ /* feedback to IPAHAL*/
+ 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);
+ return SUCCESS;
+}
+
+int IPACM_OffloadManager::post_route_evt(enum ipa_ip_type iptype, int index, ipa_cm_event_id event, const Prefix &gw_addr)
+{
+ ipacm_cmd_q_data evt;
+ ipacm_event_data_iptype *evt_data_route;
+
+ evt_data_route = (ipacm_event_data_iptype*)malloc(sizeof(ipacm_event_data_iptype));
+ if(evt_data_route == NULL)
+ {
+ IPACMERR("Failed to allocate memory.\n");
+ return -EFAULT;
+ }
+ memset(evt_data_route, 0, sizeof(*evt_data_route));
+
+ evt_data_route->if_index = index;
+ evt_data_route->if_index_tether = 0;
+ evt_data_route->iptype = iptype;
+
+#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
+ evt_data_route->ipv4_addr_gw = gw_addr.v4Addr;
+ evt_data_route->ipv6_addr_gw[0] = gw_addr.v6Addr[0];
+ evt_data_route->ipv6_addr_gw[1] = gw_addr.v6Addr[1];
+ evt_data_route->ipv6_addr_gw[2] = gw_addr.v6Addr[2];
+ evt_data_route->ipv6_addr_gw[3] = gw_addr.v6Addr[3];
+ IPACMDBG_H("default gw ipv4 (%x)\n", evt_data_route->ipv4_addr_gw);
+ IPACMDBG_H("IPV6 gateway: %08x:%08x:%08x:%08x \n",
+ evt_data_route->ipv6_addr_gw[0], evt_data_route->ipv6_addr_gw[1], evt_data_route->ipv6_addr_gw[2], evt_data_route->ipv6_addr_gw[3]);
+#endif
+ IPACMDBG_H("Received WAN_UPSTREAM_ROUTE_ADD: fid(%d) tether_fid(%d) ip-type(%d)\n", evt_data_route->if_index,
+ evt_data_route->if_index_tether, evt_data_route->iptype);
+
+ memset(&evt, 0, sizeof(evt));
+ evt.evt_data = (void*)evt_data_route;
+ evt.event = event;
+
+ IPACM_EvtDispatcher::PostEvt(&evt);
+
+ return 0;
+}
+
+int IPACM_OffloadManager::ipa_get_if_index(const char * if_name, int * if_index)
+{
+ int fd;
+ struct ifreq ifr;
+
+ if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ IPACMERR("get interface index socket create failed \n");
+ return IPACM_FAILURE;
+ }
+
+ if(strnlen(if_name, sizeof(if_name)) >= sizeof(ifr.ifr_name)) {
+ IPACMERR("interface name overflows: len %d\n", strnlen(if_name, sizeof(if_name)));
+ close(fd);
+ return IPACM_FAILURE;
+ }
+
+ memset(&ifr, 0, sizeof(struct ifreq));
+ (void)strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name));
+ IPACMDBG_H("interface name (%s)\n", if_name);
+
+ if(ioctl(fd,SIOCGIFINDEX , &ifr) < 0)
+ {
+ IPACMERR("call_ioctl_on_dev: ioctl failed, interface name (%s):\n", ifr.ifr_name);
+ close(fd);
+ return IPACM_FAILURE;
+ }
+
+ *if_index = ifr.ifr_ifindex;
+ IPACMDBG_H("Interface netdev index %d\n", *if_index);
+ close(fd);
+ return IPACM_SUCCESS;
+}
+
+int IPACM_OffloadManager::resetTetherStats(const char * upstream_name /* upstream */)
+{
+ int fd = -1;
+ wan_ioctl_reset_tether_stats stats;
+
+ if ((fd = open(DEVICE_NAME, O_RDWR)) < 0) {
+ IPACMERR("Failed opening %s.\n", DEVICE_NAME);
+ return FAIL_HARDWARE;
+ }
+
+ memset(stats.upstreamIface, 0, IFNAMSIZ);
+ if (strlcpy(stats.upstreamIface, upstream_name, IFNAMSIZ) >= IFNAMSIZ) {
+ IPACMERR("String truncation occurred on upstream\n");
+ close(fd);
+ return FAIL_INPUT_CHECK;
+ }
+ stats.reset_stats = true;
+
+ if (ioctl(fd, WAN_IOC_RESET_TETHER_STATS, &stats) < 0) {
+ IPACMERR("IOCTL WAN_IOC_RESET_TETHER_STATS call failed: %s", strerror(errno));
+ close(fd);
+ return FAIL_HARDWARE;
+ }
+ IPACMDBG_H("Reset Interface %s stats\n", upstream_name);
+ return IPACM_SUCCESS;
+}
+
+IPACM_OffloadManager* IPACM_OffloadManager::GetInstance()
+{
+ if(pInstance == NULL)
+ pInstance = new IPACM_OffloadManager();
+
+ return pInstance;
+}
diff --git a/msm8998/ipacm/src/IPACM_Wan.cpp b/msm8998/ipacm/src/IPACM_Wan.cpp
index 43bffe3..0a52ad5 100644
--- a/msm8998/ipacm/src/IPACM_Wan.cpp
+++ b/msm8998/ipacm/src/IPACM_Wan.cpp
@@ -714,13 +714,14 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
{
ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
+#ifndef FEATURE_IPACM_HAL
/* add the check see if tether_iface is valid or not */
if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE)
{
IPACMERR("UPSTREAM_ROUTE_ADD tether_if(%d), not valid ignore\n", INVALID_IFACE);
return;
}
-
+#endif
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_ADD_EVENT (Android) for ip-type (%d)\n", data->iptype);
@@ -738,12 +739,16 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
#else
IPACMDBG_H("adding routing table(upstream), dev (%s) ip-type(%d)\n", dev_name,data->iptype);
#endif
- handle_route_add_evt(data->iptype);
+ handle_route_add_evt(data->iptype); //sky
}
#ifdef FEATURE_IPA_ANDROID
+#ifdef FEATURE_IPACM_HAL
+ post_wan_up_tether_evt(data->iptype, 0);
+#else
/* using ipa_if_index, not netdev_index */
post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
#endif
+#endif
}
else if ((data->iptype == IPA_IP_v6) && (ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX))
{
@@ -770,9 +775,13 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
handle_route_add_evt(data->iptype);
}
#ifdef FEATURE_IPA_ANDROID
+#ifdef FEATURE_IPACM_HAL
+ post_wan_up_tether_evt(data->iptype, 0);
+#else
/* using ipa_if_index, not netdev_index */
post_wan_up_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
#endif
+#endif
}
}
else /* double check if current default iface is not itself */
@@ -818,13 +827,14 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
{
ipacm_event_data_iptype *data = (ipacm_event_data_iptype *)param;
ipa_interface_index = iface_ipa_index_query(data->if_index);
+#ifndef FEATURE_IPACM_HAL
/* add the check see if tether_iface is valid or not */
if (iface_ipa_index_query(data->if_index_tether) == INVALID_IFACE)
{
IPACMERR("UPSTREAM_ROUTE_DEL tether_if(%d), not valid ignore\n", INVALID_IFACE);
return;
}
-
+#endif
if (ipa_interface_index == ipa_if_num)
{
IPACMDBG_H("Received IPA_WAN_UPSTREAM_ROUTE_DEL_EVENT\n");
@@ -833,6 +843,9 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("get del default v4 route (dst:0.0.0.0)\n");
wan_v4_addr_gw_set = false;
#ifdef FEATURE_IPA_ANDROID
+#ifdef FEATURE_IPACM_HAL
+ post_wan_down_tether_evt(data->iptype, 0);
+#else
/* using ipa_if_index, not netdev_index */
post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
/* no any ipv4 tether iface support*/
@@ -842,6 +855,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
return;
}
#endif
+#endif
if(m_is_sta_mode == Q6_WAN)
{
del_wan_firewall_rule(IPA_IP_v4);
@@ -857,6 +871,10 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
else if ((data->iptype == IPA_IP_v6) && (active_v6 == true))
{
#ifdef FEATURE_IPA_ANDROID
+#ifdef FEATURE_IPACM_HAL
+ post_wan_down_tether_evt(data->iptype, 0);
+#else
+
/* using ipa_if_index, not netdev_index */
post_wan_down_tether_evt(data->iptype, iface_ipa_index_query(data->if_index_tether));
/* no any ipv6 tether iface support*/
@@ -866,6 +884,7 @@ void IPACM_Wan::event_callback(ipa_cm_event_id event, void *param)
return;
}
#endif
+#endif
if(m_is_sta_mode == Q6_WAN)
{
del_wan_firewall_rule(IPA_IP_v6);
@@ -4291,8 +4310,7 @@ int IPACM_Wan::config_dft_embms_rules(ipa_ioc_add_flt_rule *pFilteringTable_v4,
int IPACM_Wan::handle_down_evt()
{
int res = IPACM_SUCCESS;
- int i, tether_total;
- int ipa_if_num_tether_tmp[IPA_MAX_IFACE_ENTRIES];
+ int i;
IPACMDBG_H(" wan handle_down_evt \n");
@@ -4313,50 +4331,22 @@ int IPACM_Wan::handle_down_evt()
/* make sure default routing rules and firewall rules are deleted*/
if (active_v4)
{
- if (rx_prop != NULL)
- {
+ if (rx_prop != NULL)
+ {
del_dft_firewall_rules(IPA_IP_v4);
}
handle_route_del_evt(IPA_IP_v4);
IPACMDBG_H("Delete default v4 routing rules\n");
-#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
- /* posting wan_down_tether for all lan clients */
- for (i=0; i < IPACM_Wan::ipa_if_num_tether_v4_total; i++)
- {
- ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v4[i];
- }
- tether_total = IPACM_Wan::ipa_if_num_tether_v4_total;
- for (i=0; i < tether_total; i++)
- {
- post_wan_down_tether_evt(IPA_IP_v4, ipa_if_num_tether_tmp[i]);
- IPACMDBG_H("post_wan_down_tether_v4 iface(%d: %s)\n", i,
- IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
- }
-#endif
}
if (active_v6)
{
- if (rx_prop != NULL)
- {
+ if (rx_prop != NULL)
+ {
del_dft_firewall_rules(IPA_IP_v6);
}
handle_route_del_evt(IPA_IP_v6);
IPACMDBG_H("Delete default v6 routing rules\n");
-#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
- /* posting wan_down_tether for all lan clients */
- for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
- {
- ipa_if_num_tether_tmp[i] = IPACM_Wan::ipa_if_num_tether_v6[i];
- }
- tether_total = IPACM_Wan::ipa_if_num_tether_v6_total;
- for (i=0; i < tether_total; i++)
- {
- post_wan_down_tether_evt(IPA_IP_v6, ipa_if_num_tether_tmp[i]);
- IPACMDBG_H("post_wan_down_tether_v6 iface(%d: %s)\n", i,
- IPACM_Iface::ipacmcfg->iface_table[ipa_if_num_tether_tmp[i]].iface_name);
- }
-#endif
}
/* Delete default v4 RT rule */
@@ -4637,7 +4627,7 @@ int IPACM_Wan::handle_down_evt_ex()
del_wan_firewall_rule(IPA_IP_v6);
install_wan_filtering_rule(false);
handle_route_del_evt_ex(IPA_IP_v6);
-#ifdef FEATURE_IPA_ANDROID //sky
+#ifdef FEATURE_IPA_ANDROID
/* posting wan_down_tether for all lan clients */
for (i=0; i < IPACM_Wan::ipa_if_num_tether_v6_total; i++)
{
diff --git a/msm8998/ipacm/src/IPACM_Wlan.cpp b/msm8998/ipacm/src/IPACM_Wlan.cpp
index 2152c4d..b47c5ef 100644
--- a/msm8998/ipacm/src/IPACM_Wlan.cpp
+++ b/msm8998/ipacm/src/IPACM_Wlan.cpp
@@ -118,7 +118,11 @@ IPACM_Wlan::IPACM_Wlan(int iface_index) : IPACM_Lan(iface_index)
/* set the IPA-client pipe enum */
if(ipa_if_cate == WLAN_IF)
{
+#ifdef FEATURE_IPACM_HAL
+ handle_tethering_client(false, IPACM_CLIENT_MAX);
+#else
handle_tethering_client(false, IPACM_CLIENT_WLAN);
+#endif
}
#endif
return;
@@ -279,6 +283,9 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
IPACM_Lan::handle_wan_up(IPA_IP_v4);
}
}
+ IPACMDBG_H("Finished checking wan_up\n");
+ } else {
+ IPACMDBG_H("Wan_V4 haven't up yet \n");
}
if(IPACM_Wan::isWanUP_V6(ipa_if_num))
@@ -298,9 +305,10 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
IPACM_Lan::handle_wan_up(IPA_IP_v6);
}
}
+ IPACMDBG_H("Finished checking wan_up_v6\n");
+ } else {
+ IPACMDBG_H("Wan_V6 haven't up yet \n");
}
-
- IPACMDBG_H("posting IPA_HANDLE_WLAN_UP:Finished checking wan_up\n");
/* checking if SW-RT_enable */
if (IPACM_Iface::ipacmcfg->ipa_sw_rt_enable == true)
{
@@ -325,20 +333,41 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
{
- if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ IPACMERR("IPA_HANDLE_WAN_UP_TETHER tether_if(%d), not valid (%d) ignore\n", data_wan_tether->if_index_tether, ipa_if_num);
+ return;
+ }
+#endif
+ if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ {
+#ifdef FEATURE_IPACM_HAL
+ if(is_upstream_set[IPA_IP_v4] == false)
{
- if(data_wan_tether->is_sta == false)
- {
- ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
- IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
- }
- else
+ IPACMDBG_H("Add upstream for IPv4.\n");
+ is_upstream_set[IPA_IP_v4] = true;
+ if(is_downstream_set[IPA_IP_v4] == true)
{
- IPACM_Lan::handle_wan_up(IPA_IP_v4);
+ IPACMDBG_H("Downstream was set before, adding UL rules.\n");
+ if(data_wan_tether->is_sta == false)
+ {
+ ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
+ handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
+ } else {
+ handle_wan_up(IPA_IP_v4);
+ }
}
}
+#else
+ if(data_wan_tether->is_sta == false)
+ {
+ ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v4);
+ handle_wan_up_ex(ext_prop, IPA_IP_v4, 0);
+ } else {
+ handle_wan_up(IPA_IP_v4);
+ }
+#endif
}
break;
@@ -354,23 +383,48 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
IPACMDBG_H("Backhaul is sta mode?%d, if_index_tether:%d tether_if_name:%s\n", data_wan_tether->is_sta,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
{
- if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ 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
+ if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ {
+#ifdef FEATURE_IPACM_HAL
+ if(is_upstream_set[IPA_IP_v6] == false)
{
- memcpy(ipv6_prefix, data_wan_tether->ipv6_prefix, sizeof(ipv6_prefix));
- install_ipv6_prefix_flt_rule(data_wan_tether->ipv6_prefix);
+ IPACMDBG_H("Add upstream for IPv6.\n");
+ is_upstream_set[IPA_IP_v6] = true;
- if(data_wan_tether->is_sta == false)
+ if(is_downstream_set[IPA_IP_v6] == true)
{
- ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(IPA_IP_v6);
- IPACM_Lan::handle_wan_up_ex(ext_prop, IPA_IP_v6, 0);
- }
- else
- {
- IPACM_Lan::handle_wan_up(IPA_IP_v6);
+ 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)
+ {
+ 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);
+ }
}
}
+#else
+ if(data_wan_tether->is_sta == false)
+ {
+ 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
}
break;
@@ -382,23 +436,37 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
IPACMERR("No event data is found.\n");
return;
}
+ if(rx_prop == NULL)
+ {
+ 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,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
{
- if(data_wan_tether->is_sta == false && wlan_ap_index > 0)
- {
- IPACMDBG_H("This is not the first AP instance and not STA mode, ignore WAN_DOWN event.\n");
- return;
- }
- if (rx_prop != NULL)
+ 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
+ if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ {
+#ifdef FEATURE_IPACM_HAL
+ if(is_upstream_set[IPA_IP_v4] == true)
{
- if(ip_type == IPA_IP_v4 || ip_type == IPA_IP_MAX)
+ IPACMDBG_H("Del upstream for IPv4.\n");
+ is_upstream_set[IPA_IP_v4] = false;
+ 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);
}
}
+#else
+ handle_wan_down(data_wan_tether->is_sta);
+#endif
}
break;
@@ -410,25 +478,107 @@ void IPACM_Wlan::event_callback(ipa_cm_event_id event, void *param)
IPACMERR("No event data is found.\n");
return;
}
+ if(rx_prop == NULL)
+ {
+ 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,
data_wan_tether->if_index_tether,
IPACM_Iface::ipacmcfg->iface_table[data_wan_tether->if_index_tether].iface_name);
- if (data_wan_tether->if_index_tether == ipa_if_num)
+#ifndef FEATURE_IPACM_HAL
+ if (data_wan_tether->if_index_tether != ipa_if_num)
+ {
+ 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
+ if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
{
- /* clean up v6 RT rules*/
- IPACMDBG_H("Received IPA_WAN_V6_DOWN in WLAN-instance and need clean up client IPv6 address \n");
- /* reset wifi-client ipv6 rt-rules */
+#ifdef FEATURE_IPACM_HAL
+ if(is_upstream_set[IPA_IP_v6] == true)
+ {
+ IPACMDBG_H("Del upstream for IPv6.\n");
+ is_upstream_set[IPA_IP_v6] = false;
+ if(is_downstream_set[IPA_IP_v6] == true)
+ {
+ 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);
+ }
+ }
+#else
+ /* reset usb-client ipv6 rt-rules */
handle_wlan_client_reset_rt(IPA_IP_v6);
+ handle_wan_down_v6(data_wan_tether->is_sta);
+#endif
+ }
+ break;
+
+ case IPA_DOWNSTREAM_ADD:
+ {
+ ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param;
+ ipa_interface_index = iface_ipa_index_query(data->if_index);
+ if(ipa_interface_index == ipa_if_num)
+ {
+ IPACMDBG_H("Received IPA_DOWNSTREAM_ADD event.\n");
+ if(is_downstream_set[data->prefix.iptype] == false)
+ {
+ IPACMDBG_H("Add downstream for IP iptype %d.\n", data->prefix.iptype);
+ is_downstream_set[data->prefix.iptype] = true;
+ memcpy(&prefix[data->prefix.iptype], &data->prefix,
+ sizeof(prefix[data->prefix.iptype]));
+
+ if(is_upstream_set[data->prefix.iptype] == true)
+ {
+ IPACMDBG_H("Upstream was set before, adding modem UL rules.\n");
+ if(ip_type == IPA_IP_MAX || ip_type == data->prefix.iptype)
+ {
+ if (data->prefix.iptype == IPA_IP_v6) /* ipv6 only */
+ install_ipv6_prefix_flt_rule(IPACM_Wan::backhaul_ipv6_prefix);
+
+ if (IPACM_Wan::backhaul_is_sta_mode == false) /* LTE */
+ {
+ ext_prop = IPACM_Iface::ipacmcfg->GetExtProp(data->prefix.iptype);
+ handle_wan_up_ex(ext_prop, data->prefix.iptype, 0);
+ } else {
+ handle_wan_up(data->prefix.iptype); /* STA */
+ }
+ }
+ }
+ }
+ }
+ break;
+ }
- if (rx_prop != NULL)
+ case IPA_DOWNSTREAM_DEL:
+ {
+ ipacm_event_ipahal_stream *data = (ipacm_event_ipahal_stream *)param;
+ ipa_interface_index = iface_ipa_index_query(data->if_index);
+ if(ipa_interface_index == ipa_if_num)
+ {
+ IPACMDBG_H("Received IPA_DOWNSTREAM_DEL event.\n");
+ if(is_downstream_set[data->prefix.iptype] == true)
{
- if(ip_type == IPA_IP_v6 || ip_type == IPA_IP_MAX)
+ IPACMDBG_H("Del downstream for IP iptype %d.\n", data->prefix.iptype);
+ is_downstream_set[data->prefix.iptype] = false;
+
+ if(is_upstream_set[data->prefix.iptype] == true)
{
- handle_wan_down_v6(data_wan_tether->is_sta);
+ 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 */
+ } else {
+ handle_wlan_client_reset_rt(IPA_IP_v6);
+ handle_wan_down_v6(IPACM_Wan::backhaul_is_sta_mode); /* LTE STA */
+ }
}
}
}
break;
+ }
#else
case IPA_HANDLE_WAN_UP:
IPACMDBG_H("Received IPA_HANDLE_WAN_UP event\n");
@@ -1671,7 +1821,11 @@ int IPACM_Wlan::handle_down_evt()
}
}
/* reset the IPA-client pipe enum */
+#ifdef FEATURE_IPACM_HAL
+ handle_tethering_client(true, IPACM_CLIENT_MAX);
+#else
handle_tethering_client(true, IPACM_CLIENT_WLAN);
+#endif
#endif /* defined(FEATURE_IPA_ANDROID)*/
fail:
diff --git a/msm8998/ipacm/src/IPACM_Xml.cpp b/msm8998/ipacm/src/IPACM_Xml.cpp
index 120a638..b81856a 100644
--- a/msm8998/ipacm/src/IPACM_Xml.cpp
+++ b/msm8998/ipacm/src/IPACM_Xml.cpp
@@ -644,14 +644,11 @@ static int IPACM_firewall_xml_parse_tree
memset(content_buf, 0, sizeof(content_buf));
memcpy(content_buf, (void *)content, str_size);
content_buf[MAX_XML_STR_LEN-1] = '\0';
- if (content_buf > 0)
- {
- config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr_mask
- = ntohl(inet_addr(content_buf));
- IPACMDBG_H("IPv4 destination subnet mask is: %s \n", content_buf);
+ config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.u.v4.dst_addr_mask
+ = ntohl(inet_addr(content_buf));
+ IPACMDBG_H("IPv4 destination subnet mask is: %s \n", content_buf);
}
}
- }
else if (0 == IPACM_util_icmp_string((char*)xml_node->name, IPV4TypeOfService_TAG))
{
config->extd_firewall_entries[config->num_extd_firewall_entries - 1].attrib.attrib_mask |= IPA_FLT_TOS;
diff --git a/msm8998/ipanat/src/Android.mk b/msm8998/ipanat/src/Android.mk
index 22d9b0e..d95c373 100644
--- a/msm8998/ipanat/src/Android.mk
+++ b/msm8998/ipanat/src/Android.mk
@@ -17,6 +17,8 @@ endif
LOCAL_SRC_FILES := ipa_nat_drv.c \
ipa_nat_drvi.c
+
+LOCAL_MODULE_PATH_64 := $(TARGET_OUT_VENDOR)/lib64
LOCAL_CFLAGS := -DDEBUG
LOCAL_MODULE := libipanat
LOCAL_MODULE_TAGS := optional