/* * 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_ */